Blender  V2.59
editmesh_add.c
Go to the documentation of this file.
00001 /*
00002  * $Id: editmesh_add.c 36368 2011-04-28 09:50:57Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2004 by Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <math.h>
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "DNA_meshdata_types.h"
00043 #include "DNA_object_types.h"
00044 #include "DNA_scene_types.h"
00045 
00046 #include "RNA_define.h"
00047 #include "RNA_access.h"
00048 #include "RNA_enum_types.h"
00049 
00050 #include "BLI_blenlib.h"
00051 #include "BLI_math.h"
00052 #include "BLI_editVert.h"
00053 #include "BLI_utildefines.h"
00054 
00055 #include "BKE_context.h"
00056 #include "BKE_depsgraph.h"
00057 #include "BKE_library.h"
00058 #include "BKE_mesh.h"
00059 #include "BKE_report.h"
00060 
00061 #include "WM_api.h"
00062 #include "WM_types.h"
00063 
00064 #include "ED_mesh.h"
00065 #include "ED_screen.h"
00066 #include "ED_transform.h"
00067 #include "ED_view3d.h"
00068 #include "ED_object.h"
00069 
00070 #include "mesh_intern.h"
00071 
00072 /* bpymenu removed XXX */
00073 
00074 /* XXX */
00075 #define add_numbut(a, b, c, d, e, f, g) {}
00076 /* XXX */
00077 
00078 static float icovert[12][3] = {
00079         {0.0f,0.0f,-200.0f}, 
00080         {144.72f, -105.144f,-89.443f},
00081         {-55.277f, -170.128,-89.443f}, 
00082         {-178.885f,0.0f,-89.443f},
00083         {-55.277f,170.128f,-89.443f}, 
00084         {144.72f,105.144f,-89.443f},
00085         {55.277f,-170.128f,89.443f},
00086         {-144.72f,-105.144f,89.443f},
00087         {-144.72f,105.144f,89.443f},
00088         {55.277f,170.128f,89.443f},
00089         {178.885f,0.0f,89.443f},
00090         {0.0f,0.0f,200.0f}
00091 };
00092 static short icoface[20][3] = {
00093         {2,0,1},
00094         {1,0,5},
00095         {3,0,2},
00096         {4,0,3},
00097         {5,0,4},
00098         {1,5,10},
00099         {2,1,6},
00100         {3,2,7},
00101         {4,3,8},
00102         {5,4,9},
00103         {6,1,10},
00104         {7,2,6},
00105         {8,3,7},
00106         {9,4,8},
00107         {10,5,9},
00108         {6,10,11},
00109         {7,6,11},
00110         {8,7,11},
00111         {9,8,11},
00112         {10,9,11}
00113 };
00114 
00115 /* *************** add-click-mesh (extrude) operator ************** */
00116 
00117 static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
00118 {
00119         ViewContext vc;
00120         EditVert *eve;
00121         float min[3], max[3];
00122         int done= 0;
00123         short use_proj;
00124 
00125         em_setup_viewcontext(C, &vc);
00126 
00127         use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) &&     (vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE);
00128         
00129         invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); 
00130         
00131         INIT_MINMAX(min, max);
00132         
00133         for(eve= vc.em->verts.first; eve; eve= eve->next) {
00134                 if(eve->f & SELECT) {
00135                         DO_MINMAX(eve->co, min, max);
00136                         done= 1;
00137                 }
00138         }
00139 
00140         /* call extrude? */
00141         if(done) {
00142                 const short rot_src= RNA_boolean_get(op->ptr, "rotate_source");
00143                 EditEdge *eed;
00144                 float vec[3], cent[3], mat[3][3];
00145                 float nor[3]= {0.0, 0.0, 0.0};
00146                 
00147                 /* 2D normal calc */
00148                 float mval_f[2];
00149 
00150                 mval_f[0]= (float)event->mval[0];
00151                 mval_f[1]= (float)event->mval[1];
00152 
00153                 done= 0;
00154 
00155                 /* calculate the normal for selected edges */
00156                 for(eed= vc.em->edges.first; eed; eed= eed->next) {
00157                         if(eed->f & SELECT) {
00158                                 float co1[3], co2[3];
00159                                 mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
00160                                 mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
00161                                 project_float_noclip(vc.ar, co1, co1);
00162                                 project_float_noclip(vc.ar, co2, co2);
00163                                 
00164                                 /* 2D rotate by 90d while adding.
00165                                  *  (x, y) = (y, -x)
00166                                  *
00167                                  * accumulate the screenspace normal in 2D,
00168                                  * with screenspace edge length weighting the result. */
00169                                 if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
00170                                         nor[0] +=  (co1[1] - co2[1]);
00171                                         nor[1] += -(co1[0] - co2[0]);
00172                                 }
00173                                 else {
00174                                         nor[0] +=  (co2[1] - co1[1]);
00175                                         nor[1] += -(co2[0] - co1[0]);
00176                                 }
00177                                 done= 1;
00178                         }
00179                 }
00180 
00181                 if(done) {
00182                         float view_vec[3], cross[3];
00183 
00184                         /* convert the 2D nomal into 3D */
00185                         mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
00186                         mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
00187                         
00188                         /* correct the normal to be aligned on the view plane */
00189                         copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
00190                         mul_mat3_m4_v3(vc.obedit->imat, view_vec);
00191                         cross_v3_v3v3(cross, nor, view_vec);
00192                         cross_v3_v3v3(nor, view_vec, cross);
00193                         normalize_v3(nor);
00194                 }
00195                 
00196                 /* center */
00197                 mid_v3_v3v3(cent, min, max);
00198                 copy_v3_v3(min, cent);
00199                 
00200                 mul_m4_v3(vc.obedit->obmat, min);       // view space
00201                 view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
00202                 mul_m4_v3(vc.obedit->imat, min); // back in object space
00203                 
00204                 sub_v3_v3(min, cent);
00205                 
00206                 /* calculate rotation */
00207                 unit_m3(mat);
00208                 if(done) {
00209                         float dot;
00210                         
00211                         copy_v3_v3(vec, min);
00212                         normalize_v3(vec);
00213                         dot= INPR(vec, nor);
00214 
00215                         if( fabs(dot)<0.999) {
00216                                 float cross[3], si, q1[4];
00217                                 
00218                                 cross_v3_v3v3(cross, nor, vec);
00219                                 normalize_v3(cross);
00220                                 dot= 0.5f*saacos(dot);
00221                                 
00222                                 /* halve the rotation if its applied twice */
00223                                 if(rot_src) dot *= 0.5f;
00224                                 
00225                                 si= (float)sin(dot);
00226                                 q1[0]= (float)cos(dot);
00227                                 q1[1]= cross[0]*si;
00228                                 q1[2]= cross[1]*si;
00229                                 q1[3]= cross[2]*si;                             
00230                                 quat_to_mat3( mat,q1);
00231                         }
00232                 }
00233                 
00234                 if(rot_src) {
00235                         rotateflag(vc.em, SELECT, cent, mat);
00236                         /* also project the source, for retopo workflow */
00237                         if(use_proj)
00238                                 EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
00239                 }
00240                 
00241                 extrudeflag(vc.obedit, vc.em, SELECT, nor, 0);
00242                 rotateflag(vc.em, SELECT, cent, mat);
00243                 translateflag(vc.em, SELECT, min);
00244                 
00245                 recalc_editnormals(vc.em);
00246         }
00247         else if(vc.em->selectmode & SCE_SELECT_VERTEX) {
00248 
00249                 float imat[4][4];
00250                 const float *curs= give_cursor(vc.scene, vc.v3d);
00251                 
00252                 copy_v3_v3(min, curs);
00253                 view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
00254 
00255                 eve= addvertlist(vc.em, 0, NULL);
00256 
00257                 invert_m4_m4(imat, vc.obedit->obmat);
00258                 mul_v3_m4v3(eve->co, imat, min);
00259                 
00260                 eve->f= SELECT;
00261         }
00262 
00263         if(use_proj)
00264                 EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
00265 
00266         WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); 
00267         DAG_id_tag_update(vc.obedit->data, 0);
00268         
00269         return OPERATOR_FINISHED;
00270 }
00271 
00272 void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
00273 {
00274         /* identifiers */
00275         ot->name= "Duplicate or Extrude at 3D Cursor";
00276         ot->description= "Duplicate and extrude selected vertices, edges or faces towards 3D Cursor";
00277         ot->idname= "MESH_OT_dupli_extrude_cursor";
00278         
00279         /* api callbacks */
00280         ot->invoke= dupli_extrude_cursor;
00281         ot->poll= ED_operator_editmesh;
00282         
00283         /* flags */
00284         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00285 
00286         RNA_def_boolean(ot->srna, "rotate_source", 1, "Rotate Source", "Rotate initial selection giving better shape");
00287 }
00288 
00289 
00290 /* ********************** */
00291 
00292 /* selected faces get hidden edges */
00293 static int make_fgon(EditMesh *em, wmOperator *op, int make)
00294 {
00295         EditFace *efa;
00296         EditEdge *eed;
00297         EditVert *eve;
00298         float *nor=NULL;        // reference
00299         int done=0;
00300         
00301         if(make==0) {
00302                 for(efa= em->faces.first; efa; efa= efa->next) {
00303                         if(efa->f & SELECT) {
00304                                 efa->fgonf= 0;
00305                                 efa->e1->h &= ~EM_FGON;
00306                                 efa->e2->h &= ~EM_FGON;
00307                                 efa->e3->h &= ~EM_FGON;
00308                                 if(efa->e4) efa->e4->h &= ~EM_FGON;
00309                                 done= 1;
00310                         }
00311                 }
00312                 EM_fgon_flags(em);      // redo flags and indices for fgons
00313                 
00314                 return done;
00315         }
00316 
00317         /* tagging edges. rule is:
00318            - edge used by exactly 2 selected faces
00319            - no vertices allowed with only tagged edges (return)
00320            - face normals are allowed to difffer
00321          
00322         */
00323         for(eed= em->edges.first; eed; eed= eed->next) {
00324                 eed->f1= 0;     // amount of selected
00325                 eed->f2= 0; // amount of unselected
00326         }
00327         
00328         for(efa= em->faces.first; efa; efa= efa->next) {
00329                 if(efa->f & SELECT) {
00330                         if(nor==NULL) nor= efa->n;
00331                         if(efa->e1->f1 < 3) efa->e1->f1++;
00332                         if(efa->e2->f1 < 3) efa->e2->f1++;
00333                         if(efa->e3->f1 < 3) efa->e3->f1++;
00334                         if(efa->e4 && efa->e4->f1 < 3) efa->e4->f1++;
00335                 }
00336                 else {
00337                         if(efa->e1->f2 < 3) efa->e1->f2++;
00338                         if(efa->e2->f2 < 3) efa->e2->f2++;
00339                         if(efa->e3->f2 < 3) efa->e3->f2++;
00340                         if(efa->e4 && efa->e4->f2 < 3) efa->e4->f2++;
00341                 }
00342         }
00343         // now eed->f1 becomes tagged edge
00344         for(eed= em->edges.first; eed; eed= eed->next) {
00345                 if(eed->f1==2 && eed->f2==0) eed->f1= 1;
00346                 else eed->f1= 0;
00347         }
00348         
00349         // no vertices allowed with only tagged edges
00350         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
00351         for(eed= em->edges.first; eed; eed= eed->next) {
00352                 if(eed->f1) {
00353                         eed->v1->f1 |= 1;
00354                         eed->v2->f1 |= 1;
00355                 }
00356                 else {
00357                         eed->v1->f1 |= 2;
00358                         eed->v2->f1 |= 2;
00359                 }
00360         }
00361         for(eve= em->verts.first; eve; eve= eve->next) {
00362                 if(eve->f1==1) break;
00363         }
00364         if(eve) {
00365                 BKE_report(op->reports, RPT_WARNING, "Cannot make a polygon with interior vertices");
00366                 return 0;
00367         }
00368         
00369         // check for faces
00370         if(nor==NULL) {
00371                 BKE_report(op->reports, RPT_WARNING, "No faces were selected to make FGon");
00372                 return 0;
00373         }
00374 
00375         // and there we go
00376         for(eed= em->edges.first; eed; eed= eed->next) {
00377                 if(eed->f1) {
00378                         eed->h |= EM_FGON;
00379                         done= 1;
00380                 }
00381         }
00382         
00383         if(done)
00384                 EM_fgon_flags(em);      // redo flags and indices for fgons
00385         return done;
00386 }
00387 
00388 static int make_fgon_exec(bContext *C, wmOperator *op)
00389 {
00390         Object *obedit= CTX_data_edit_object(C);
00391         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
00392 
00393         if( make_fgon(em, op, 1) ) {
00394                 DAG_id_tag_update(obedit->data, 0);
00395                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
00396 
00397                 BKE_mesh_end_editmesh(obedit->data, em);
00398                 return OPERATOR_FINISHED;
00399         }
00400 
00401         BKE_mesh_end_editmesh(obedit->data, em);
00402         return OPERATOR_CANCELLED;
00403 }
00404 
00405 void MESH_OT_fgon_make(struct wmOperatorType *ot)
00406 {
00407         /* identifiers */
00408         ot->name= "Make F-gon";
00409         ot->description= "Make fgon from selected faces";
00410         ot->idname= "MESH_OT_fgon_make";
00411         
00412         /* api callbacks */
00413         ot->exec= make_fgon_exec;
00414         ot->poll= ED_operator_editmesh;
00415         
00416         /* flags */
00417         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00418 }
00419 
00420 static int clear_fgon_exec(bContext *C, wmOperator *op)
00421 {
00422         Object *obedit= CTX_data_edit_object(C);
00423         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
00424         
00425         if( make_fgon(em, op, 0) ) {
00426                 DAG_id_tag_update(obedit->data, 0);
00427                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
00428                 
00429                 BKE_mesh_end_editmesh(obedit->data, em);
00430                 return OPERATOR_FINISHED;
00431         }
00432 
00433         BKE_mesh_end_editmesh(obedit->data, em);
00434         return OPERATOR_CANCELLED;
00435 }
00436 
00437 void MESH_OT_fgon_clear(struct wmOperatorType *ot)
00438 {
00439         /* identifiers */
00440         ot->name= "Clear F-gon";
00441         ot->description= "Clear fgon from selected face";
00442         ot->idname= "MESH_OT_fgon_clear";
00443         
00444         /* api callbacks */
00445         ot->exec= clear_fgon_exec;
00446         ot->poll= ED_operator_editmesh;
00447         
00448         /* flags */
00449         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00450 }
00451 
00452 /* precondition; 4 vertices selected, check for 4 edges and create face */
00453 static EditFace *addface_from_edges(EditMesh *em)
00454 {
00455         EditEdge *eed, *eedar[4]={NULL, NULL, NULL, NULL};
00456         EditVert *v1=NULL, *v2=NULL, *v3=NULL, *v4=NULL;
00457         int a;
00458         
00459         /* find the 4 edges */
00460         for(eed= em->edges.first; eed; eed= eed->next) {
00461                 if( (eed->f & SELECT) || (eed->v1->f & eed->v2->f & SELECT) ) {
00462                         if(eedar[0]==NULL) eedar[0]= eed;
00463                         else if(eedar[1]==NULL) eedar[1]= eed;
00464                         else if(eedar[2]==NULL) eedar[2]= eed;
00465                         else eedar[3]= eed;
00466                         
00467                 }
00468         }
00469         
00470         
00471         if(eedar[3]) {
00472                 /* first 2 points */
00473                 v1= eedar[0]->v1;
00474                 v2= eedar[0]->v2;
00475                 
00476                 /* find the 2 edges connected to first edge */
00477                 for(a=1; a<4; a++) {
00478                         if( eedar[a]->v1 == v2) v3= eedar[a]->v2;
00479                         else if(eedar[a]->v2 == v2) v3= eedar[a]->v1;
00480                         else if( eedar[a]->v1 == v1) v4= eedar[a]->v2;
00481                         else if(eedar[a]->v2 == v1) v4= eedar[a]->v1;
00482                 }
00483                 
00484                 /* verify if last edge exists */
00485                 if(v3 && v4) {
00486                         for(a=1; a<4; a++) {
00487                                 if( eedar[a]->v1==v3 && eedar[a]->v2==v4) break;
00488                                 if( eedar[a]->v2==v3 && eedar[a]->v1==v4) break;
00489                         }
00490                         if(a!=4) {
00491                                 return addfacelist(em, v1, v2, v3, v4, NULL, NULL);
00492                         }
00493                 }
00494         }
00495         return NULL;
00496 }
00497 
00498 /* ******************************* */
00499 
00500 /* this also allows to prevent triangles being made in quads */
00501 static int compareface_overlaps(EditFace *vl1, EditFace *vl2)
00502 {
00503         EditVert *v1, *v2, *v3, *v4;
00504         int equal= 0;
00505         
00506         v1= vl2->v1;
00507         v2= vl2->v2;
00508         v3= vl2->v3;
00509         v4= vl2->v4;
00510         
00511         if(vl1==vl2) return 0;
00512         
00513         if(v4==NULL && vl1->v4==NULL) {
00514                 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) equal++;
00515                 if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) equal++;
00516                 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) equal++;
00517         }
00518         else {
00519                 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) equal++;
00520                 if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) equal++;
00521                 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) equal++;
00522                 if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) equal++;
00523         }
00524 
00525         if(v4 && vl1->v4) {
00526                 if(equal==4) return 1;
00527         }
00528         else 
00529                 if(equal>=3) return 1;
00530         
00531         return 0;
00532 }
00533 
00534 /* checks for existence, and for tria overlapping inside quad */
00535 static EditFace *exist_face_overlaps(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
00536 {
00537         EditFace *efa, efatest;
00538         
00539         efatest.v1= v1;
00540         efatest.v2= v2;
00541         efatest.v3= v3;
00542         efatest.v4= v4;
00543         
00544         efa= em->faces.first;
00545         while(efa) {
00546                 if(compareface_overlaps(&efatest, efa)) return efa;
00547                 efa= efa->next;
00548         }
00549         return NULL;
00550 }
00551 
00552 /* will be new face smooth or solid? depends on smoothness of face neighbours
00553  * of new face, if function return 1, then new face will be smooth, when functio
00554  * will return zero, then new face will be solid */
00555 static void fix_new_face(EditMesh *em, EditFace *eface)
00556 {
00557         struct EditFace *efa;
00558         struct EditEdge *eed=NULL;
00559         struct EditVert *v1 = eface->v1, *v2 = eface->v2, *v3 = eface->v3, *v4 = eface->v4;
00560         struct EditVert *ev1=NULL, *ev2=NULL;
00561         short smooth=0; /* "total smoothnes" of faces in neighbourhood */
00562         short coef;     /* "weight" of smoothness */
00563         short count=0;  /* number of edges with same direction as eface */
00564         short vi00=0, vi01=0, vi10=0, vi11=0; /* vertex indexes */
00565 
00566         efa = em->faces.first;
00567 
00568         while(efa) {
00569 
00570                 if(efa==eface) {
00571                         efa = efa->next;
00572                         continue;
00573                 }
00574 
00575                 coef = 0;
00576                 ev1 = ev2 = NULL;
00577                 eed = NULL;
00578 
00579                 if(efa->v1==v1 || efa->v2==v1 || efa->v3==v1 || efa->v4==v1) {
00580                         ev1 = v1;
00581                         coef++;
00582                 }
00583                 if(efa->v1==v2 || efa->v2==v2 || efa->v3==v2 || efa->v4==v2) {
00584                         if(ev1) ev2 = v2;
00585                         else ev1 = v2;
00586                         coef++;
00587                 }
00588                 if(efa->v1==v3 || efa->v2==v3 || efa->v3==v3 || efa->v4==v3) {
00589                         if(coef<2) {
00590                                 if(ev1) ev2 = v3;
00591                                 else ev1 = v3;
00592                         }
00593                         coef++;
00594                 }
00595                 if((v4) && (efa->v1==v4 || efa->v2==v4 || efa->v3==v4 || efa->v4==v4)) {
00596                         if(ev1 && coef<2) ev2 = v4;
00597                         coef++;
00598                 }
00599 
00600                 /* "democracy" of smoothness */
00601                 if(efa->flag & ME_SMOOTH)
00602                         smooth += coef;
00603                 else
00604                         smooth -= coef;
00605 
00606                 /* try to find edge using vertexes ev1 and ev2 */
00607                 if((ev1) && (ev2) && (ev1!=ev2)) eed = findedgelist(em, ev1, ev2);
00608 
00609                 /* has bordering edge of efa same direction as edge of eface ? */
00610                 if(eed) {
00611                         if(eed->v1==v1) vi00 = 1;
00612                         else if(eed->v1==v2) vi00 = 2;
00613                         else if(eed->v1==v3) vi00 = 3;
00614                         else if(v4 && eed->v1==v4) vi00 = 4;
00615 
00616                         if(eed->v2==v1) vi01 = 1;
00617                         else if(eed->v2==v2) vi01 = 2;
00618                         else if(eed->v2==v3) vi01 = 3;
00619                         else if(v4 && eed->v2==v4) vi01 = 4;
00620 
00621                         if(v4) {
00622                                 if(vi01==1 && vi00==4) vi00 = 0;
00623                                 if(vi01==4 && vi00==1) vi01 = 0;
00624                         }
00625                         else {
00626                                 if(vi01==1 && vi00==3) vi00 = 0;
00627                                 if(vi01==3 && vi00==1) vi01 = 0;
00628                         }
00629 
00630                         if(eed->v1==efa->v1) vi10 = 1;
00631                         else if(eed->v1==efa->v2) vi10 = 2;
00632                         else if(eed->v1==efa->v3) vi10 = 3;
00633                         else if(efa->v4 && eed->v1==efa->v4) vi10 = 4;
00634 
00635                         if(eed->v2==efa->v1) vi11 = 1;
00636                         else if(eed->v2==efa->v2) vi11 = 2;
00637                         else if(eed->v2==efa->v3) vi11 = 3;
00638                         else if(efa->v4 && eed->v2==efa->v4) vi11 = 4;
00639 
00640                         if(efa->v4) {
00641                                 if(vi11==1 && vi10==4) vi10 = 0;
00642                                 if(vi11==4 && vi10==1) vi11 = 0;
00643                         }
00644                         else {
00645                                 if(vi11==1 && vi10==3) vi10 = 0;
00646                                 if(vi11==3 && vi10==1) vi11 = 0;
00647                         }
00648 
00649                         if(((vi00>vi01) && (vi10>vi11)) ||
00650                                 ((vi00<vi01) && (vi10<vi11)))
00651                                 count++;
00652                         else
00653                                 count--;
00654                 }
00655 
00656                 efa = efa->next;
00657         }
00658 
00659         /* set up smoothness according voting of face in neighbourhood */
00660         if(smooth >= 0)
00661                 eface->flag |= ME_SMOOTH;
00662         else
00663                 eface->flag &= ~ME_SMOOTH;
00664 
00665         /* flip face, when too much "face normals" in neighbourhood is different */
00666         if(count > 0) {
00667                 flipface(em, eface);
00668         }
00669 }
00670 
00671 /* only adds quads or trias when there's edges already */
00672 static void addfaces_from_edgenet(EditMesh *em)
00673 {
00674         EditVert *eve1, *eve2, *eve3, *eve4;
00675         
00676         for(eve1= em->verts.first; eve1; eve1= eve1->next) {
00677                 for(eve2= em->verts.first; (eve1->f & 1) && eve2; eve2= eve2->next) {
00678                         if(findedgelist(em, eve1,eve2)) {
00679                                 for(eve3= em->verts.first; (eve2->f & 1) && eve3; eve3= eve3->next) {
00680                                         if((eve2!=eve3 && (eve3->f & 1) && findedgelist(em, eve1,eve3))) {
00681                                                 EditEdge *sh_edge= NULL;
00682                                                 EditVert *sh_vert= NULL;
00683                                                 
00684                                                 sh_edge= findedgelist(em, eve2,eve3);
00685                                                 
00686                                                 if(sh_edge) { /* Add a triangle */
00687                                                         if(!exist_face_overlaps(em, eve1,eve2,eve3,NULL))
00688                                                                 fix_new_face(em, addfacelist(em, eve1,eve2,eve3,NULL,NULL,NULL));
00689                                                 }
00690                                                 else { /* Check for a shared vertex */
00691                                                         for(eve4= em->verts.first; eve4; eve4= eve4->next) {
00692                                                                 if(eve4!=eve1 && eve4!=eve2 && eve4!=eve3 && (eve4->f & 1) &&
00693                                                                    !findedgelist(em, eve1,eve4) && findedgelist(em, eve2,eve4) &&
00694                                                                    findedgelist(em, eve3,eve4)) {
00695                                                                         sh_vert= eve4;
00696                                                                         break;
00697                                                                 }
00698                                                         }
00699                                                         
00700                                                         if(sh_vert) {
00701                                                                 if(sh_vert) {
00702                                                                         if(!exist_face_overlaps(em, eve1,eve2,eve4,eve3))
00703                                                                                 fix_new_face(em, addfacelist(em, eve1,eve2,eve4,eve3,NULL,NULL));
00704                                                                 }
00705                                                         }
00706                                                 }
00707                                         }
00708                                 }
00709                         }
00710                 }
00711         }
00712 
00713         EM_select_flush(em);
00714         
00715 // XXX  DAG_id_tag_update(obedit->data, 0);
00716 }
00717 
00718 static void addedgeface_mesh(EditMesh *em, wmOperator *op)
00719 {
00720         EditVert *eve, *neweve[4];
00721         EditEdge *eed;
00722         EditFace *efa;
00723         short amount=0;
00724 
00725         /* how many selected ? */
00726         if(em->selectmode & SCE_SELECT_EDGE) {
00727                 /* in edge mode finding selected vertices means flushing down edge codes... */
00728                 /* can't make face with only edge selection info... */
00729                 EM_selectmode_set(em);
00730         }
00731         
00732         for(eve= em->verts.first; eve; eve= eve->next) {
00733                 if(eve->f & SELECT) {
00734                         amount++;
00735                         if(amount>4) break;                     
00736                         neweve[amount-1]= eve;
00737                 }
00738         }
00739 
00740         if(amount==2) {
00741                 eed= addedgelist(em, neweve[0], neweve[1], NULL);
00742                 EM_select_edge(eed, 1);
00743 
00744                 // XXX          DAG_id_tag_update(obedit->data, 0);
00745                 return;
00746         }
00747         else if(amount > 4) {
00748                 addfaces_from_edgenet(em);
00749                 return;
00750         }
00751         else if(amount<2) {
00752                 BKE_report(op->reports, RPT_WARNING, "More vertices are needed to make an edge/face");
00753                 return;
00754         }
00755 
00756         efa= NULL; // check later
00757 
00758         if(amount==3) {
00759                 
00760                 if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], NULL)==0) {
00761                         efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
00762                         EM_select_face(efa, 1);
00763                 }
00764                 else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
00765         }
00766         else if(amount==4) {
00767                 /* this test survives when theres 2 triangles */
00768                 if(exist_face(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
00769                         int tria= 0;
00770                         
00771                         /* remove trias if they exist, 4 cases.... */
00772                         if(exist_face(em, neweve[0], neweve[1], neweve[2], NULL)) tria++;
00773                         if(exist_face(em, neweve[0], neweve[1], neweve[3], NULL)) tria++;
00774                         if(exist_face(em, neweve[0], neweve[2], neweve[3], NULL)) tria++;
00775                         if(exist_face(em, neweve[1], neweve[2], neweve[3], NULL)) tria++;
00776                 
00777                         if(tria==2) join_triangles(em);
00778                         else if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
00779                                  /* If there are 4 Verts, But more selected edges, we need to call addfaces_from_edgenet */
00780                                         EditEdge *eedcheck;
00781                                         int count;
00782                                         count = 0;
00783                                         for(eedcheck= em->edges.first; eedcheck; eedcheck= eedcheck->next) {
00784                                                 if(eedcheck->f & SELECT) {
00785                                                         count++;
00786                                                 }
00787                                         }       
00788                                 
00789                                 if(count++ > 4){
00790                                         addfaces_from_edgenet(em);
00791                                         return;
00792                                 } else {
00793                                 /* if 4 edges exist, we just create the face, convex or not */
00794                                         efa= addface_from_edges(em);
00795                                         if(efa==NULL) {
00796                                                 
00797                                                 /* the order of vertices can be anything, 6 cases to check */
00798                                                 if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
00799                                                         efa= addfacelist(em, neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
00800                                                 }
00801                                                 else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
00802                                                         efa= addfacelist(em, neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
00803                                                 }
00804                                                 else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
00805                                                         efa= addfacelist(em, neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
00806                                                 }
00807                                                 else if( convex(neweve[0]->co, neweve[1]->co, neweve[3]->co, neweve[2]->co) ) {
00808                                                         efa= addfacelist(em, neweve[0], neweve[1], neweve[3], neweve[2], NULL, NULL);
00809                                                 }
00810                                                 else if( convex(neweve[0]->co, neweve[3]->co, neweve[2]->co, neweve[1]->co) ) {
00811                                                         efa= addfacelist(em, neweve[0], neweve[3], neweve[2], neweve[1], NULL, NULL);
00812                                                 }
00813                                                 else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) {
00814                                                         efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL);
00815                                                 }
00816                                                 else BKE_report(op->reports, RPT_WARNING, "cannot find nice quad from concave set of vertices");
00817 
00818                                         }
00819                                 }
00820                         }
00821                         else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
00822                 }
00823                 else BKE_report(op->reports, RPT_WARNING, "The selected vertices already form a face");
00824         }
00825         
00826         if(efa) {
00827                 EM_select_face(efa, 1);
00828 
00829                 fix_new_face(em, efa);
00830                 
00831                 recalc_editnormals(em);
00832         }
00833         }
00834 
00835 static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
00836 {
00837         Object *obedit= CTX_data_edit_object(C);
00838         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
00839         
00840         addedgeface_mesh(em, op);
00841         
00842         DAG_id_tag_update(obedit->data, 0);
00843         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
00844         
00845         BKE_mesh_end_editmesh(obedit->data, em);
00846         return OPERATOR_FINISHED;
00847 }
00848 
00849 void MESH_OT_edge_face_add(wmOperatorType *ot)
00850 {
00851         /* identifiers */
00852         ot->name= "Make Edge/Face";
00853         ot->description= "Add an edge or face to selected";
00854         ot->idname= "MESH_OT_edge_face_add";
00855         
00856         /* api callbacks */
00857         ot->exec= addedgeface_mesh_exec;
00858         ot->poll= ED_operator_editmesh;
00859         
00860         /* flags */
00861         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00862         
00863 }
00864 
00865 
00866 
00867 /* ************************ primitives ******************* */
00868 
00869 // HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker
00870 // this hack is only used so that scons+mingw + split-sources hack works
00871         // ------------------------------- start copied code
00872 /* these are not the monkeys you are looking for */
00873 static int monkeyo= 4;
00874 static int monkeynv= 271;
00875 static int monkeynf= 250;
00876 static signed char monkeyv[271][3]= {
00877 {-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92},
00878 {-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83},
00879 {-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102},
00880 {-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92},
00881 {-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74},
00882 {-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99},
00883 {-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105},
00884 {-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100},
00885 {-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100},
00886 {-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73},
00887 {-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45},
00888 {-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68},
00889 {-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68},
00890 {-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80},
00891 {-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96},
00892 {-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90},
00893 {-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85},
00894 {-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94},
00895 {-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96},
00896 {-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95},
00897 {-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84},
00898 {-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109},
00899 {-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88},
00900 {-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82},
00901 {-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96},
00902 {-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96},
00903 {-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100},
00904 {-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104},
00905 {-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71},
00906 {-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88},
00907 {-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84},
00908 {-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81},
00909 {-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99},
00910 {-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87},
00911 {-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100},
00912 {-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97},
00913 {-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86},
00914 {-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96},
00915 {-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79},
00916 {-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59},
00917 {-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37},
00918 {-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59},
00919 {-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7},
00920 {-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9},
00921 {-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52},
00922 {-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51},
00923 {-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55},
00924 {-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34},
00925 {-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30},
00926 {-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7},
00927 {-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57},
00928 {-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26},
00929 {-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16},
00930 {6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54},
00931 {4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52},
00932 {28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28},
00933 {-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57},
00934 {31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27},
00935 {-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35},
00936 {-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24},
00937 {-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41},
00938 {-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41},
00939 {6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62},
00940 {7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42},
00941 {-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48},
00942 {8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62},
00943 {33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63},
00944 {-26,-16,-42},{-17,49,-49},
00945 };
00946 
00947 static signed char monkeyf[250][4]= {
00948 {27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4}, 
00949 {3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6}, 
00950 {5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8}, 
00951 {7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12}, 
00952 {5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12}, 
00953 {-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4}, 
00954 {10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4}, 
00955 {5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23}, 
00956 {20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15}, 
00957 {12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, 
00958 {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, 
00959 {18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44}, 
00960 {24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19}, 
00961 {16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38}, 
00962 {8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39}, 
00963 {16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42}, 
00964 {19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16}, 
00965 {13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32}, 
00966 {-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35}, 
00967 {34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21}, 
00968 {1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11}, 
00969 {35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38}, 
00970 {-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39}, 
00971 {33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34}, 
00972 {8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34}, 
00973 {-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36}, 
00974 {-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27}, 
00975 {-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42}, 
00976 {25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34}, 
00977 {25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26}, 
00978 {23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35}, 
00979 {-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35}, 
00980 {-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58}, 
00981 {40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52}, 
00982 {-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49}, 
00983 {43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24}, 
00984 {-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100}, 
00985 {-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24}, 
00986 {-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110}, 
00987 {6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48}, 
00988 {17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43}, 
00989 {35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6}, 
00990 {-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30}, 
00991 {4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5}, 
00992 {-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13}, 
00993 {-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30}, 
00994 {-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31}, 
00995 {30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35}, 
00996 {32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27}, 
00997 {25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23}, 
00998 {11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35}, 
00999 {32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4}, 
01000 {-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35}, 
01001 {24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33}, 
01002 {24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35}, 
01003 {11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36}, 
01004 {35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39}, 
01005 {18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17}, 
01006 {24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19}, 
01007 {16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30}, 
01008 {-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30}, 
01009 {23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66}, 
01010 {-68,-67,24,-33}, 
01011 };
01012         // ------------------------------- end copied code
01013 
01014 
01015 #define PRIM_PLANE              0
01016 #define PRIM_CUBE               1
01017 #define PRIM_CIRCLE             4
01018 #define PRIM_CYLINDER   5
01019 #define PRIM_CONE               7
01020 #define PRIM_GRID               10
01021 #define PRIM_UVSPHERE   11
01022 #define PRIM_ICOSPHERE  12
01023 #define PRIM_MONKEY             13
01024 
01025 static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg,
01026                 int subdiv, float dia, float depth, int ext, int fill)
01027 {
01028         /*
01029          * type - for the type of shape
01030          * dia - the radius for cone,sphere cylinder etc.
01031          * depth - 
01032          * ext - extrude
01033          * fill - end capping, and option to fill in circle
01034          * cent[3] - center of the data. 
01035          * */
01036         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
01037         EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
01038         float phi, phid, vec[3];
01039         float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0};
01040         short a, b;
01041         
01042         EM_clear_flag_all(em, SELECT);
01043 
01044         phid= 2.0f*(float)M_PI/tot;
01045         phi= .25f*(float)M_PI;
01046 
01047         switch(type) {
01048         case PRIM_GRID: /*  grid */
01049                 /* clear flags */
01050                 eve= em->verts.first;
01051                 while(eve) {
01052                         eve->f= 0;
01053                         eve= eve->next;
01054                 }
01055                 
01056                 /* one segment first: the X axis */             
01057                 phi = (2*dia)/(float)(tot-1);
01058                 phid = (2*dia)/(float)(seg-1);
01059                 for(a=tot-1;a>=0;a--) {
01060                         vec[0] = (phi*a) - dia;
01061                         vec[1]= - dia;
01062                         vec[2]= 0.0f;
01063                         eve= addvertlist(em, vec, NULL);
01064                         eve->f= 1+2+4;
01065                         if(a < tot -1) addedgelist(em, eve->prev, eve, NULL);
01066                 }
01067                 /* extrude and translate */
01068                 vec[0]= vec[2]= 0.0;
01069                 vec[1]= phid;
01070                 
01071                 for(a=0;a<seg-1;a++) {
01072                         extrudeflag_vert(obedit, em, 2, nor, 0);        // nor unused
01073                         translateflag(em, 2, vec);
01074                 }
01075                         
01076                 /* and now do imat */
01077                 eve= em->verts.first;
01078                 while(eve) {
01079                         if(eve->f & SELECT) {
01080                                 mul_m4_v3(mat,eve->co);
01081                         }
01082                         eve= eve->next;
01083                 }
01084                 recalc_editnormals(em);
01085                 break;
01086                         
01087         case PRIM_UVSPHERE: /*  UVsphere */
01088                 
01089                 /* clear all flags */
01090                 eve= em->verts.first;
01091                 while(eve) {
01092                         eve->f= 0;
01093                         eve= eve->next;
01094                 }
01095                 
01096                 /* one segment first */
01097                 phi= 0; 
01098                 phid/=2;
01099                 for(a=0; a<=tot; a++) {
01100                         vec[0]= dia*sinf(phi);
01101                         vec[1]= 0.0;
01102                         vec[2]= dia*cosf(phi);
01103                         eve= addvertlist(em, vec, NULL);
01104                         eve->f= 1+2+4;
01105                         if(a==0) v1= eve;
01106                         else addedgelist(em, eve, eve->prev, NULL);
01107                         phi+= phid;
01108                 }
01109                 
01110                 /* extrude and rotate */
01111                 phi= M_PI/seg;
01112                 q[0]= cos(phi);
01113                 q[3]= sin(phi);
01114                 q[1]=q[2]= 0;
01115                 quat_to_mat3( cmat,q);
01116                 
01117                 for(a=0; a<seg; a++) {
01118                         extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused
01119                         rotateflag(em, 2, v1->co, cmat);
01120                 }
01121 
01122                 removedoublesflag(em, 4, 0, 0.0001);
01123 
01124                 /* and now do imat */
01125                 eve= em->verts.first;
01126                 while(eve) {
01127                         if(eve->f & SELECT) {
01128                                 mul_m4_v3(mat,eve->co);
01129                         }
01130                         eve= eve->next;
01131                 }
01132                 recalc_editnormals(em);
01133                 break;
01134         case PRIM_ICOSPHERE: /* Icosphere */
01135                 {
01136                         EditVert *eva[12];
01137                         EditEdge *eed;
01138                         
01139                         /* clear all flags */
01140                         eve= em->verts.first;
01141                         while(eve) {
01142                                 eve->f= 0;
01143                                 eve= eve->next;
01144                         }
01145                         dia/=200;
01146                         for(a=0;a<12;a++) {
01147                                 vec[0]= dia*icovert[a][0];
01148                                 vec[1]= dia*icovert[a][1];
01149                                 vec[2]= dia*icovert[a][2];
01150                                 eva[a]= addvertlist(em, vec, NULL);
01151                                 eva[a]->f= 1+2;
01152                         }
01153                         for(a=0;a<20;a++) {
01154                                 EditFace *evtemp;
01155                                 v1= eva[ icoface[a][0] ];
01156                                 v2= eva[ icoface[a][1] ];
01157                                 v3= eva[ icoface[a][2] ];
01158                                 evtemp = addfacelist(em, v1, v2, v3, 0, NULL, NULL);
01159                                 evtemp->e1->f = 1+2;
01160                                 evtemp->e2->f = 1+2;
01161                                 evtemp->e3->f = 1+2;
01162                         }
01163 
01164                         dia*=200;
01165                         for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0, B_SPHERE,1, SUBDIV_CORNER_PATH, 0);
01166                         /* and now do imat */
01167                         eve= em->verts.first;
01168                         while(eve) {
01169                                 if(eve->f & 2) {
01170                                         mul_m4_v3(mat,eve->co);
01171                                 }
01172                                 eve= eve->next;
01173                         }
01174                         
01175                         // Clear the flag 2 from the edges
01176                         for(eed=em->edges.first;eed;eed=eed->next){
01177                                 if(eed->f & 2){
01178                                            eed->f &= !2;
01179                                 }   
01180                         }
01181                 }
01182                 break;
01183         case PRIM_MONKEY: /* Monkey */
01184                 {
01185                         //extern int monkeyo, monkeynv, monkeynf;
01186                         //extern signed char monkeyf[][4];
01187                         //extern signed char monkeyv[][3];
01188                         EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv");
01189                         int i;
01190 
01191                         for (i=0; i<monkeynv; i++) {
01192                                 float v[3];
01193                                 v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
01194                                 tv[i]= addvertlist(em, v, NULL);
01195                                 tv[i]->f |= SELECT;
01196                                 tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(em, v, NULL);
01197                                 tv[monkeynv+i]->f |= SELECT;
01198                         }
01199                         for (i=0; i<monkeynf; i++) {
01200                                 addfacelist(em, tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
01201                                 addfacelist(em, tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
01202                         }
01203 
01204                         MEM_freeN(tv);
01205 
01206                         /* and now do imat */
01207                         for(eve= em->verts.first; eve; eve= eve->next) {
01208                                 if(eve->f & SELECT) {
01209                                         mul_m4_v3(mat,eve->co);
01210                                 }
01211                         }
01212                         recalc_editnormals(em);
01213                 }
01214                 break;
01215         default: /* all types except grid, sphere... */
01216                 if(type==PRIM_CONE);
01217                 else if(ext==0) 
01218                         depth= 0.0f;
01219         
01220                 /* first vertex at 0° for circular objects */
01221                 if( ELEM3(type, PRIM_CIRCLE,PRIM_CYLINDER,PRIM_CONE) )
01222                         phi = 0.0f;
01223                         
01224                 vtop= vdown= v1= v2= 0;
01225                 for(b=0; b<=ext; b++) {
01226                         for(a=0; a<tot; a++) {
01227                                 
01228                                 vec[0]= dia*sinf(phi);
01229                                 vec[1]= dia*cosf(phi);
01230                                 vec[2]= b?depth:-depth;
01231                                 
01232                                 mul_m4_v3(mat, vec);
01233                                 eve= addvertlist(em, vec, NULL);
01234                                 eve->f= SELECT;
01235                                 if(a==0) {
01236                                         if(b==0) v1= eve;
01237                                         else v2= eve;
01238                                 }
01239                                 phi+=phid;
01240                         }
01241                 }
01242                         
01243                 /* center vertices */
01244                 /* type PRIM_CONE can only have 1 one side filled
01245                  * if the cone has no capping, dont add vtop */
01246                 if(type == PRIM_CONE || (fill && !ELEM(type, PRIM_PLANE, PRIM_CUBE))) {
01247                         vec[0]= vec[1]= 0.0f;
01248                         vec[2]= type==PRIM_CONE ? depth : -depth;
01249                         mul_m4_v3(mat, vec);
01250                         vdown= addvertlist(em, vec, NULL);
01251                         if((ext || type==PRIM_CONE) && fill) {
01252                                 vec[0]= vec[1]= 0.0f;
01253                                 vec[2]= type==PRIM_CONE ? -depth : depth;
01254                                 mul_m4_v3(mat,vec);
01255                                 vtop= addvertlist(em, vec, NULL);
01256                         }
01257                 } else {
01258                         vdown= v1;
01259                         vtop= v2;
01260                 }
01261                 if(vtop) vtop->f= SELECT;
01262                 if(vdown) vdown->f= SELECT;
01263         
01264                 /* top and bottom face */
01265                 if(fill || type==PRIM_CONE) {
01266                         if(tot==4 && ELEM(type, PRIM_PLANE, PRIM_CUBE)) {
01267                                 v3= v1->next->next;
01268                                 if(ext) v4= v2->next->next;
01269                                 
01270                                 addfacelist(em, v3, v1->next, v1, v3->next, NULL, NULL);
01271                                 if(ext) addfacelist(em, v2, v2->next, v4, v4->next, NULL, NULL);
01272                                 
01273                         }
01274                         else {
01275                                 v3= v1;
01276                                 v4= v2;
01277                                 for(a=1; a<tot; a++) {
01278                                         addfacelist(em, vdown, v3, v3->next, 0, NULL, NULL);
01279                                         v3= v3->next;
01280                                         if(ext && fill) {
01281                                                 addfacelist(em, vtop, v4, v4->next, 0, NULL, NULL);
01282                                                 v4= v4->next;
01283                                         }
01284                                 }
01285                                 if(!ELEM(type, PRIM_PLANE, PRIM_CUBE)) {
01286                                         addfacelist(em, vdown, v3, v1, 0, NULL, NULL);
01287                                         if(ext) addfacelist(em, vtop, v4, v2, 0, NULL, NULL);
01288                                 }
01289                         }
01290                 }
01291                 else if(type==PRIM_CIRCLE) {  /* we need edges for a circle */
01292                         v3= v1;
01293                         for(a=1;a<tot;a++) {
01294                                 addedgelist(em, v3, v3->next, NULL);
01295                                 v3= v3->next;
01296                         }
01297                         addedgelist(em, v3, v1, NULL);
01298                 }
01299                 /* side faces */
01300                 if(ext) {
01301                         v3= v1;
01302                         v4= v2;
01303                         for(a=1; a<tot; a++) {
01304                                 addfacelist(em, v3, v3->next, v4->next, v4, NULL, NULL);
01305                                 v3= v3->next;
01306                                 v4= v4->next;
01307                         }
01308                         addfacelist(em, v3, v1, v2, v4, NULL, NULL);
01309                 }
01310                 else if(fill && type==PRIM_CONE) {
01311                         /* add the bottom flat area of the cone
01312                          * if capping is disabled dont bother */
01313                         v3= v1;
01314                         for(a=1; a<tot; a++) {
01315                                 addfacelist(em, vtop, v3->next, v3, 0, NULL, NULL);
01316                                 v3= v3->next;
01317                         }
01318                         addfacelist(em, vtop, v1, v3, 0, NULL, NULL);
01319                 }
01320         }
01321         
01322         EM_stats_update(em);
01323         /* simple selection flush OK, based on fact it's a single model */
01324         EM_select_flush(em); /* flushes vertex -> edge -> face selection */
01325 
01326         if(!ELEM5(type, PRIM_GRID, PRIM_PLANE, PRIM_ICOSPHERE, PRIM_UVSPHERE, PRIM_MONKEY))
01327                 EM_recalc_normal_direction(em, FALSE, TRUE);    /* otherwise monkey has eyes in wrong direction */
01328 
01329         BKE_mesh_end_editmesh(obedit->data, em);
01330 }
01331 
01332 /* ********* add primitive operators ************* */
01333 
01334 static const char *get_mesh_defname(int type)
01335 {
01336         switch (type) {
01337                 case PRIM_PLANE: return "Plane";
01338                 case PRIM_CUBE: return "Cube";
01339                 case PRIM_CIRCLE: return "Circle";
01340                 case PRIM_CYLINDER: return "Cylinder";
01341                 case PRIM_CONE: return "Cone";
01342                 case PRIM_GRID: return "Grid";
01343                 case PRIM_UVSPHERE: return "Sphere";
01344                 case PRIM_ICOSPHERE: return "Icosphere";
01345                 case PRIM_MONKEY: return "Monkey";
01346                 default:
01347                         return "Mesh";
01348         }
01349 }
01350 
01351 static void make_prim_ext(bContext *C, float *loc, float *rot, int enter_editmode, unsigned int layer, 
01352                 int type, int tot, int seg,
01353                 int subdiv, float dia, float depth, int ext, int fill)
01354 {
01355         Object *obedit= CTX_data_edit_object(C);
01356         int newob = 0;
01357         float mat[4][4];
01358         float scale;
01359 
01360         if(obedit==NULL || obedit->type!=OB_MESH) {
01361                 obedit= ED_object_add_type(C, OB_MESH, loc, rot, FALSE, layer);
01362                 
01363                 rename_id((ID *)obedit, get_mesh_defname(type));
01364                 rename_id((ID *)obedit->data, get_mesh_defname(type));
01365                 
01366                 /* create editmode */
01367                 ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
01368                 newob = 1;
01369         }
01370         else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
01371 
01372         scale= ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
01373 
01374         dia *= scale;
01375         depth *= scale * 0.5f;
01376 
01377         make_prim(obedit, type, mat, tot, seg, subdiv, dia, depth, ext, fill);
01378 
01379         DAG_id_tag_update(obedit->data, 0);
01380         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
01381 
01382 
01383         /* userdef */
01384         if (newob && !enter_editmode) {
01385                 ED_object_exit_editmode(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */
01386         }
01387         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
01388 }
01389 
01390 static int add_primitive_plane_exec(bContext *C, wmOperator *op)
01391 {
01392         int enter_editmode;
01393         unsigned int layer;
01394         float loc[3], rot[3];
01395         
01396         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01397                 return OPERATOR_CANCELLED;
01398 
01399         /* sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */
01400         make_prim_ext(C, loc, rot, enter_editmode, layer,
01401                         PRIM_PLANE, 4, 0, 0, sqrt(2.0f), 0.0f, 0, 1);
01402         return OPERATOR_FINISHED;       
01403 }
01404 
01405 void MESH_OT_primitive_plane_add(wmOperatorType *ot)
01406 {
01407         /* identifiers */
01408         ot->name= "Add Plane";
01409         ot->description= "Construct a filled planar mesh with 4 vertices";
01410         ot->idname= "MESH_OT_primitive_plane_add";
01411         
01412         /* api callbacks */
01413         ot->invoke= ED_object_add_generic_invoke;
01414         ot->exec= add_primitive_plane_exec;
01415         ot->poll= ED_operator_scene_editable;
01416         
01417         /* flags */
01418         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01419 
01420         ED_object_add_generic_props(ot, TRUE);
01421 }
01422 
01423 static int add_primitive_cube_exec(bContext *C, wmOperator *op)
01424 {
01425         int enter_editmode;
01426         unsigned int layer;
01427         float loc[3], rot[3];
01428         
01429         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01430                 return OPERATOR_CANCELLED;
01431 
01432         /* sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */
01433         make_prim_ext(C, loc, rot, enter_editmode, layer,
01434                         PRIM_CUBE, 4, 0, 0, sqrt(2.0f), 2.0f, 1, 1);
01435         return OPERATOR_FINISHED;
01436 }
01437 
01438 void MESH_OT_primitive_cube_add(wmOperatorType *ot)
01439 {
01440         /* identifiers */
01441         ot->name= "Add Cube";
01442         ot->description= "Construct a cube mesh";
01443         ot->idname= "MESH_OT_primitive_cube_add";
01444         
01445         /* api callbacks */
01446         ot->invoke= ED_object_add_generic_invoke;
01447         ot->exec= add_primitive_cube_exec;
01448         ot->poll= ED_operator_scene_editable;
01449         
01450         /* flags */
01451         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01452 
01453         ED_object_add_generic_props(ot, TRUE);
01454 }
01455 
01456 static int add_primitive_circle_exec(bContext *C, wmOperator *op)
01457 {
01458         int enter_editmode;
01459         unsigned int layer;
01460         float loc[3], rot[3];
01461         
01462         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01463                 return OPERATOR_CANCELLED;
01464 
01465         make_prim_ext(C, loc, rot, enter_editmode, layer,
01466                         PRIM_CIRCLE, RNA_int_get(op->ptr, "vertices"), 0, 0,
01467                         RNA_float_get(op->ptr,"radius"), 0.0f, 0,
01468                         RNA_boolean_get(op->ptr, "fill"));
01469 
01470         return OPERATOR_FINISHED;       
01471 }
01472 
01473 void MESH_OT_primitive_circle_add(wmOperatorType *ot)
01474 {
01475         /* identifiers */
01476         ot->name= "Add Circle";
01477         ot->description= "Construct a circle mesh";
01478         ot->idname= "MESH_OT_primitive_circle_add";
01479         
01480         /* api callbacks */
01481         ot->invoke= ED_object_add_generic_invoke;
01482         ot->exec= add_primitive_circle_exec;
01483         ot->poll= ED_operator_scene_editable;
01484         
01485         /* flags */
01486         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01487         
01488         /* props */
01489         RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 3, 500);
01490         RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
01491         RNA_def_boolean(ot->srna, "fill", 0, "Fill", "");
01492 
01493         ED_object_add_generic_props(ot, TRUE);
01494 }
01495 
01496 static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
01497 {
01498         int enter_editmode;
01499         unsigned int layer;
01500         float loc[3], rot[3];
01501         
01502         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01503                 return OPERATOR_CANCELLED;
01504 
01505         make_prim_ext(C, loc, rot, enter_editmode, layer,
01506                         PRIM_CYLINDER, RNA_int_get(op->ptr, "vertices"), 0, 0,
01507                         RNA_float_get(op->ptr,"radius"),
01508                         RNA_float_get(op->ptr, "depth"), 1, 
01509                         RNA_boolean_get(op->ptr, "cap_ends"));
01510 
01511         return OPERATOR_FINISHED;
01512 }
01513 
01514 void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
01515 {
01516         /* identifiers */
01517         ot->name= "Add Cylinder";
01518         ot->description= "Construct a cylinder mesh";
01519         ot->idname= "MESH_OT_primitive_cylinder_add";
01520         
01521         /* api callbacks */
01522         ot->invoke= ED_object_add_generic_invoke;
01523         ot->exec= add_primitive_cylinder_exec;
01524         ot->poll= ED_operator_scene_editable;
01525         
01526         /* flags */
01527         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01528         
01529         /* props */
01530         RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
01531         RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
01532         RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
01533         RNA_def_boolean(ot->srna, "cap_ends", 1, "Cap Ends", "");
01534 
01535         ED_object_add_generic_props(ot, TRUE);
01536 }
01537 
01538 static int add_primitive_cone_exec(bContext *C, wmOperator *op)
01539 {
01540         int enter_editmode;
01541         unsigned int layer;
01542         float loc[3], rot[3];
01543         
01544         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01545                 return OPERATOR_CANCELLED;
01546 
01547         make_prim_ext(C, loc, rot, enter_editmode, layer,
01548                         PRIM_CONE, RNA_int_get(op->ptr, "vertices"), 0, 0,
01549                         RNA_float_get(op->ptr,"radius"), RNA_float_get(op->ptr, "depth"),
01550                         0, RNA_boolean_get(op->ptr, "cap_end"));
01551 
01552         return OPERATOR_FINISHED;
01553 }
01554 
01555 void MESH_OT_primitive_cone_add(wmOperatorType *ot)
01556 {
01557         /* identifiers */
01558         ot->name= "Add Cone";
01559         ot->description= "Construct a conic mesh (ends filled)";
01560         ot->idname= "MESH_OT_primitive_cone_add";
01561         
01562         /* api callbacks */
01563         ot->invoke= ED_object_add_generic_invoke;
01564         ot->exec= add_primitive_cone_exec;
01565         ot->poll= ED_operator_scene_editable;
01566         
01567         /* flags */
01568         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01569         
01570         /* props */
01571         RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
01572         RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
01573         RNA_def_float(ot->srna, "depth", 2.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
01574         RNA_def_boolean(ot->srna, "cap_end", 1, "Cap End", "");
01575 
01576         ED_object_add_generic_props(ot, TRUE);
01577 }
01578 
01579 static int add_primitive_grid_exec(bContext *C, wmOperator *op)
01580 {
01581         int enter_editmode;
01582         unsigned int layer;
01583         float loc[3], rot[3];
01584         
01585         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01586                 return OPERATOR_CANCELLED;
01587 
01588         make_prim_ext(C, loc, rot, enter_editmode, layer,
01589                         PRIM_GRID, RNA_int_get(op->ptr, "x_subdivisions"),
01590                         RNA_int_get(op->ptr, "y_subdivisions"), 0,
01591                         RNA_float_get(op->ptr,"size"), 0.0f, 0, 1);
01592 
01593         return OPERATOR_FINISHED;
01594 }
01595 
01596 void MESH_OT_primitive_grid_add(wmOperatorType *ot)
01597 {
01598         /* identifiers */
01599         ot->name= "Add Grid";
01600         ot->description= "Construct a grid mesh";
01601         ot->idname= "MESH_OT_primitive_grid_add";
01602         
01603         /* api callbacks */
01604         ot->invoke= ED_object_add_generic_invoke;
01605         ot->exec= add_primitive_grid_exec;
01606         ot->poll= ED_operator_scene_editable;
01607         
01608         /* flags */
01609         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01610         
01611         /* props */
01612         RNA_def_int(ot->srna, "x_subdivisions", 10, INT_MIN, INT_MAX, "X Subdivisions", "", 3, 1000);
01613         RNA_def_int(ot->srna, "y_subdivisions", 10, INT_MIN, INT_MAX, "Y Subdivisions", "", 3, 1000);
01614         RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, FLT_MAX);
01615 
01616         ED_object_add_generic_props(ot, TRUE);
01617 }
01618 
01619 static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
01620 {
01621         int enter_editmode;
01622         unsigned int layer;
01623         float loc[3], rot[3];
01624         
01625         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01626                 return OPERATOR_CANCELLED;
01627 
01628         make_prim_ext(C, loc, rot, enter_editmode, layer,
01629                         PRIM_MONKEY, 0, 0, 2, 0.0f, 0.0f, 0, 0);
01630 
01631         return OPERATOR_FINISHED;
01632 }
01633 
01634 void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
01635 {
01636         /* identifiers */
01637         ot->name= "Add Monkey";
01638         ot->description= "Construct a Suzanne mesh";
01639         ot->idname= "MESH_OT_primitive_monkey_add";
01640         
01641         /* api callbacks */
01642         ot->invoke= ED_object_add_generic_invoke;
01643         ot->exec= add_primitive_monkey_exec;
01644         ot->poll= ED_operator_scene_editable;
01645         
01646         /* flags */
01647         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01648 
01649         ED_object_add_generic_props(ot, TRUE);
01650 }
01651 
01652 static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
01653 {
01654         int enter_editmode;
01655         unsigned int layer;
01656         float loc[3], rot[3];
01657         
01658         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01659                 return OPERATOR_CANCELLED;
01660 
01661         make_prim_ext(C, loc, rot, enter_editmode, layer,
01662                         PRIM_UVSPHERE, RNA_int_get(op->ptr, "ring_count"),
01663                         RNA_int_get(op->ptr, "segments"), 0,
01664                         RNA_float_get(op->ptr,"size"), 0.0f, 0, 0);
01665 
01666         return OPERATOR_FINISHED;       
01667 }
01668 
01669 void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
01670 {
01671         /* identifiers */
01672         ot->name= "Add UV Sphere";
01673         ot->description= "Construct a UV sphere mesh";
01674         ot->idname= "MESH_OT_primitive_uv_sphere_add";
01675         
01676         /* api callbacks */
01677         ot->invoke= ED_object_add_generic_invoke;
01678         ot->exec= add_primitive_uvsphere_exec;
01679         ot->poll= ED_operator_scene_editable;
01680         
01681         /* flags */
01682         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01683         
01684         /* props */
01685         RNA_def_int(ot->srna, "segments", 32, INT_MIN, INT_MAX, "Segments", "", 3, 500);
01686         RNA_def_int(ot->srna, "ring_count", 16, INT_MIN, INT_MAX, "Rings", "", 3, 500);
01687         RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, 100.00);
01688 
01689         ED_object_add_generic_props(ot, TRUE);
01690 }
01691 
01692 static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
01693 {
01694         int enter_editmode;
01695         unsigned int layer;
01696         float loc[3], rot[3];
01697         
01698         if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
01699                 return OPERATOR_CANCELLED;
01700 
01701         make_prim_ext(C, loc, rot, enter_editmode, layer,
01702                         PRIM_ICOSPHERE, 0, 0, RNA_int_get(op->ptr, "subdivisions"),
01703                         RNA_float_get(op->ptr,"size"), 0.0f, 0, 0);
01704 
01705         return OPERATOR_FINISHED;       
01706 }
01707 
01708 void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
01709 {
01710         /* identifiers */
01711         ot->name= "Add Ico Sphere";
01712         ot->description= "Construct an Icosphere mesh";
01713         ot->idname= "MESH_OT_primitive_ico_sphere_add";
01714         
01715         /* api callbacks */
01716         ot->invoke= ED_object_add_generic_invoke;
01717         ot->exec= add_primitive_icosphere_exec;
01718         ot->poll= ED_operator_scene_editable;
01719         
01720         /* flags */
01721         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01722         
01723         /* props */
01724         RNA_def_int(ot->srna, "subdivisions", 2, 0, INT_MAX, "Subdivisions", "", 0, 8);
01725         RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
01726 
01727         ED_object_add_generic_props(ot, TRUE);
01728 }
01729 
01730 /****************** add duplicate operator ***************/
01731 
01732 static int mesh_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
01733 {
01734         Object *ob= CTX_data_edit_object(C);
01735         EditMesh *em= BKE_mesh_get_editmesh(ob->data);
01736 
01737         adduplicateflag(em, SELECT);
01738 
01739         BKE_mesh_end_editmesh(ob->data, em);
01740 
01741         DAG_id_tag_update(ob->data, 0);
01742         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
01743         
01744         return OPERATOR_FINISHED;
01745 }
01746 
01747 static int mesh_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01748 {
01749         WM_cursor_wait(1);
01750         mesh_duplicate_exec(C, op);
01751         WM_cursor_wait(0);
01752         
01753         return OPERATOR_FINISHED;
01754 }
01755 
01756 void MESH_OT_duplicate(wmOperatorType *ot)
01757 {
01758         /* identifiers */
01759         ot->name= "Duplicate Mesh";
01760         ot->description= "Duplicate selected vertices, edges or faces";
01761         ot->idname= "MESH_OT_duplicate";
01762         
01763         /* api callbacks */
01764         ot->invoke= mesh_duplicate_invoke;
01765         ot->exec= mesh_duplicate_exec;
01766         
01767         ot->poll= ED_operator_editmesh;
01768         
01769         /* to give to transform */
01770         RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", "");
01771 }
01772