Did some code cleanups. Added BM_ITER and
[blender.git] / source / blender / editors / mesh / editmesh_add.c
1 /**
2  * $Id: 
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2004 by Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_mesh_types.h"
38 #include "DNA_meshdata_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_screen_types.h"
43 #include "DNA_userdef_types.h"
44 #include "DNA_view3d_types.h"
45 #include "DNA_windowmanager_types.h"
46
47 #include "RNA_types.h"
48 #include "RNA_define.h"
49 #include "RNA_access.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_arithb.h"
53 #include "BLI_editVert.h"
54
55 #include "BKE_context.h"
56 #include "BKE_depsgraph.h"
57 #include "BKE_global.h"
58 #include "BKE_library.h"
59 #include "BKE_mesh.h"
60 #include "BKE_object.h"
61 #include "BKE_utildefines.h"
62 #include "BKE_report.h"
63 #include "BKE_tessmesh.h"
64
65 #include "BIF_retopo.h"
66
67 #include "WM_api.h"
68 #include "WM_types.h"
69
70 #include "ED_mesh.h"
71 #include "ED_util.h"
72 #include "ED_view3d.h"
73 #include "ED_screen.h"
74
75 #include "bmesh.h"
76
77 #include "mesh_intern.h"
78
79 /* bpymenu removed XXX */
80
81 /* XXX */
82 #define add_numbut(a, b, c, d, e, f, g) {}
83 /* XXX */
84
85 static float icovert[12][3] = {
86         {0.0f,0.0f,-200.0f}, 
87         {144.72f, -105.144f,-89.443f},
88         {-55.277f, -170.128,-89.443f}, 
89         {-178.885f,0.0f,-89.443f},
90         {-55.277f,170.128f,-89.443f}, 
91         {144.72f,105.144f,-89.443f},
92         {55.277f,-170.128f,89.443f},
93         {-144.72f,-105.144f,89.443f},
94         {-144.72f,105.144f,89.443f},
95         {55.277f,170.128f,89.443f},
96         {178.885f,0.0f,89.443f},
97         {0.0f,0.0f,200.0f}
98 };
99 static short icoface[20][3] = {
100         {1,0,2},
101         {1,0,5},
102         {2,0,3},
103         {3,0,4},
104         {4,0,5},
105         {1,5,10},
106         {2,1,6},
107         {3,2,7},
108         {4,3,8},
109         {5,4,9},
110         {10,1,6},
111         {6,2,7},
112         {7,3,8},
113         {8,4,9},
114         {9,5,10},
115         {6,10,11},
116         {7,6,11},
117         {8,7,11},
118         {9,8,11},
119         {10,9,11}
120 };
121
122 /* *************** add-click-mesh (extrude) operator ************** */
123
124 static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
125 {
126 #if 0 //BMESH_TODO
127         ViewContext vc;
128         EditVert *eve, *v1;
129         float min[3], max[3];
130         int done= 0;
131         
132         em_setup_viewcontext(C, &vc);
133         
134         INIT_MINMAX(min, max);
135         
136         for(v1= vc.em->verts.first;v1; v1=v1->next) {
137                 if(v1->f & SELECT) {
138                         DO_MINMAX(v1->co, min, max);
139                         done= 1;
140                 }
141         }
142
143         /* call extrude? */
144         if(done) {
145                 EditEdge *eed;
146                 float vec[3], cent[3], mat[3][3];
147                 float nor[3]= {0.0, 0.0, 0.0};
148                 
149                 /* check for edges that are half selected, use for rotation */
150                 done= 0;
151                 for(eed= vc.em->edges.first; eed; eed= eed->next) {
152                         if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) {
153                                 if(eed->v1->f & SELECT) VecSubf(vec, eed->v1->co, eed->v2->co);
154                                 else VecSubf(vec, eed->v2->co, eed->v1->co);
155                                 VecAddf(nor, nor, vec);
156                                 done= 1;
157                         }
158                 }
159                 if(done) Normalize(nor);
160                 
161                 /* center */
162                 VecAddf(cent, min, max);
163                 VecMulf(cent, 0.5f);
164                 VECCOPY(min, cent);
165                 
166                 Mat4MulVecfl(vc.obedit->obmat, min);    // view space
167                 view3d_get_view_aligned_coordinate(&vc, min, event->mval);
168                 Mat4Invert(vc.obedit->imat, vc.obedit->obmat); 
169                 Mat4MulVecfl(vc.obedit->imat, min); // back in object space
170                 
171                 VecSubf(min, min, cent);
172                 
173                 /* calculate rotation */
174                 Mat3One(mat);
175                 if(done) {
176                         float dot;
177                         
178                         VECCOPY(vec, min);
179                         Normalize(vec);
180                         dot= INPR(vec, nor);
181
182                         if( fabs(dot)<0.999) {
183                                 float cross[3], si, q1[4];
184                                 
185                                 Crossf(cross, nor, vec);
186                                 Normalize(cross);
187                                 dot= 0.5f*saacos(dot);
188                                 si= (float)sin(dot);
189                                 q1[0]= (float)cos(dot);
190                                 q1[1]= cross[0]*si;
191                                 q1[2]= cross[1]*si;
192                                 q1[3]= cross[2]*si;
193                                 
194                                 QuatToMat3(q1, mat);
195                         }
196                 }
197                 
198                 extrudeflag(vc.obedit, vc.em, SELECT, nor);
199                 rotateflag(vc.em, SELECT, cent, mat);
200                 translateflag(vc.em, SELECT, min);
201                 
202                 recalc_editnormals(vc.em);
203         }
204         else {
205                 float mat[3][3],imat[3][3];
206                 float *curs= give_cursor(vc.scene, vc.v3d);
207                 
208                 VECCOPY(min, curs);
209                 view3d_get_view_aligned_coordinate(&vc, min, event->mval);
210                 
211                 eve= addvertlist(vc.em, 0, NULL);
212
213                 Mat3CpyMat4(mat, vc.obedit->obmat);
214                 Mat3Inv(imat, mat);
215                 
216                 VECCOPY(eve->co, min);
217                 Mat3MulVecfl(imat, eve->co);
218                 VecSubf(eve->co, eve->co, vc.obedit->obmat[3]);
219                 
220                 eve->f= SELECT;
221         }
222         
223         //retopo_do_all();
224         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit); 
225         DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA);
226         
227         return OPERATOR_FINISHED;
228 #endif
229 }
230
231 void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot)
232 {
233         /* identifiers */
234         ot->name= "Duplicate or Extrude at 3D Cursor";
235         ot->idname= "MESH_OT_dupli_extrude_cursor";
236         
237         /* api callbacks */
238         ot->invoke= dupli_extrude_cursor;
239         ot->poll= ED_operator_editmesh;
240         
241         /* flags */
242         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
243 }
244
245
246 /* ********************** */
247
248 /* selected faces get hidden edges */
249 int make_fgon(EditMesh *em, wmOperator *op, int make)
250 {
251         EditFace *efa;
252         EditEdge *eed;
253         EditVert *eve;
254         float *nor=NULL;        // reference
255         int done=0;
256         
257         if(make==0) {
258                 for(efa= em->faces.first; efa; efa= efa->next) {
259                         if(efa->f & SELECT) {
260                                 efa->fgonf= 0;
261                                 efa->e1->h &= ~EM_FGON;
262                                 efa->e2->h &= ~EM_FGON;
263                                 efa->e3->h &= ~EM_FGON;
264                                 if(efa->e4) efa->e4->h &= ~EM_FGON;
265                                 done= 1;
266                         }
267                 }
268                 EM_fgon_flags(em);      // redo flags and indices for fgons
269                 
270                 return done;
271         }
272
273         /* tagging edges. rule is:
274            - edge used by exactly 2 selected faces
275            - no vertices allowed with only tagged edges (return)
276            - face normals are allowed to difffer
277          
278         */
279         for(eed= em->edges.first; eed; eed= eed->next) {
280                 eed->f1= 0;     // amount of selected
281                 eed->f2= 0; // amount of unselected
282         }
283         
284         for(efa= em->faces.first; efa; efa= efa->next) {
285                 if(efa->f & SELECT) {
286                         if(nor==NULL) nor= efa->n;
287                         if(efa->e1->f1 < 3) efa->e1->f1++;
288                         if(efa->e2->f1 < 3) efa->e2->f1++;
289                         if(efa->e3->f1 < 3) efa->e3->f1++;
290                         if(efa->e4 && efa->e4->f1 < 3) efa->e4->f1++;
291                 }
292                 else {
293                         if(efa->e1->f2 < 3) efa->e1->f2++;
294                         if(efa->e2->f2 < 3) efa->e2->f2++;
295                         if(efa->e3->f2 < 3) efa->e3->f2++;
296                         if(efa->e4 && efa->e4->f2 < 3) efa->e4->f2++;
297                 }
298         }
299         // now eed->f1 becomes tagged edge
300         for(eed= em->edges.first; eed; eed= eed->next) {
301                 if(eed->f1==2 && eed->f2==0) eed->f1= 1;
302                 else eed->f1= 0;
303         }
304         
305         // no vertices allowed with only tagged edges
306         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
307         for(eed= em->edges.first; eed; eed= eed->next) {
308                 if(eed->f1) {
309                         eed->v1->f1 |= 1;
310                         eed->v2->f1 |= 1;
311                 }
312                 else {
313                         eed->v1->f1 |= 2;
314                         eed->v2->f1 |= 2;
315                 }
316         }
317         for(eve= em->verts.first; eve; eve= eve->next) {
318                 if(eve->f1==1) break;
319         }
320         if(eve) {
321                 BKE_report(op->reports, RPT_ERROR, "Cannot make a polygon with interior vertices");
322                 return 0;
323         }
324         
325         // check for faces
326         if(nor==NULL) {
327                 BKE_report(op->reports, RPT_ERROR, "No faces were selected to make FGon");
328                 return 0;
329         }
330
331         // and there we go
332         for(eed= em->edges.first; eed; eed= eed->next) {
333                 if(eed->f1) {
334                         eed->h |= EM_FGON;
335                         done= 1;
336                 }
337         }
338         
339         if(done)
340                 EM_fgon_flags(em);      // redo flags and indices for fgons
341         return done;
342 }
343
344 static int make_fgon_exec(bContext *C, wmOperator *op)
345 {
346         Object *obedit= CTX_data_edit_object(C);
347         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
348
349         if( make_fgon(em, op, 1) ) {
350                 DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);     
351         
352                 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
353
354                 BKE_mesh_end_editmesh(obedit->data, em);
355                 return OPERATOR_FINISHED;
356         }
357
358         BKE_mesh_end_editmesh(obedit->data, em);
359         return OPERATOR_CANCELLED;
360 }
361
362 void MESH_OT_fgon_make(struct wmOperatorType *ot)
363 {
364         /* identifiers */
365         ot->name= "Make F-gon";
366         ot->idname= "MESH_OT_fgon_make";
367         
368         /* api callbacks */
369         ot->exec= make_fgon_exec;
370         ot->poll= ED_operator_editmesh;
371         
372         /* flags */
373         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
374 }
375
376 static int clear_fgon_exec(bContext *C, wmOperator *op)
377 {
378         Object *obedit= CTX_data_edit_object(C);
379         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
380         
381         if( make_fgon(em, op, 0) ) {
382                 DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);     
383                 
384                 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
385                 
386                 BKE_mesh_end_editmesh(obedit->data, em);
387                 return OPERATOR_FINISHED;
388         }
389
390         BKE_mesh_end_editmesh(obedit->data, em);
391         return OPERATOR_CANCELLED;
392 }
393
394 void MESH_OT_fgon_clear(struct wmOperatorType *ot)
395 {
396         /* identifiers */
397         ot->name= "Clear F-gon";
398         ot->idname= "MESH_OT_fgon_clear";
399         
400         /* api callbacks */
401         ot->exec= clear_fgon_exec;
402         ot->poll= ED_operator_editmesh;
403         
404         /* flags */
405         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
406 }
407
408 /* precondition; 4 vertices selected, check for 4 edges and create face */
409 static EditFace *addface_from_edges(EditMesh *em)
410 {
411         EditEdge *eed, *eedar[4]={NULL, NULL, NULL, NULL};
412         EditVert *v1=NULL, *v2=NULL, *v3=NULL, *v4=NULL;
413         int a;
414         
415         /* find the 4 edges */
416         for(eed= em->edges.first; eed; eed= eed->next) {
417                 if( (eed->f & SELECT) || (eed->v1->f & eed->v2->f & SELECT) ) {
418                         if(eedar[0]==NULL) eedar[0]= eed;
419                         else if(eedar[1]==NULL) eedar[1]= eed;
420                         else if(eedar[2]==NULL) eedar[2]= eed;
421                         else eedar[3]= eed;
422                         
423                 }
424         }
425         
426         
427         if(eedar[3]) {
428                 /* first 2 points */
429                 v1= eedar[0]->v1;
430                 v2= eedar[0]->v2;
431                 
432                 /* find the 2 edges connected to first edge */
433                 for(a=1; a<4; a++) {
434                         if( eedar[a]->v1 == v2) v3= eedar[a]->v2;
435                         else if(eedar[a]->v2 == v2) v3= eedar[a]->v1;
436                         else if( eedar[a]->v1 == v1) v4= eedar[a]->v2;
437                         else if(eedar[a]->v2 == v1) v4= eedar[a]->v1;
438                 }
439                 
440                 /* verify if last edge exists */
441                 if(v3 && v4) {
442                         for(a=1; a<4; a++) {
443                                 if( eedar[a]->v1==v3 && eedar[a]->v2==v4) break;
444                                 if( eedar[a]->v2==v3 && eedar[a]->v1==v4) break;
445                         }
446                         if(a!=4) {
447                                 return addfacelist(em, v1, v2, v3, v4, NULL, NULL);
448                         }
449                 }
450         }
451         return NULL;
452 }
453
454 /* ******************************* */
455
456 /* this also allows to prevent triangles being made in quads */
457 static int compareface_overlaps(EditFace *vl1, EditFace *vl2)
458 {
459         EditVert *v1, *v2, *v3, *v4;
460         int equal= 0;
461         
462         v1= vl2->v1;
463         v2= vl2->v2;
464         v3= vl2->v3;
465         v4= vl2->v4;
466         
467         if(vl1==vl2) return 0;
468         
469         if(v4==NULL && vl1->v4==NULL) {
470                 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) equal++;
471                 if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) equal++;
472                 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) equal++;
473         }
474         else {
475                 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) equal++;
476                 if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) equal++;
477                 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) equal++;
478                 if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) equal++;
479         }
480
481         if(v4 && vl1->v4) {
482                 if(equal==4) return 1;
483         }
484         else 
485                 if(equal>=3) return 1;
486         
487         return 0;
488 }
489
490 /* checks for existance, and for tria overlapping inside quad */
491 static EditFace *exist_face_overlaps(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
492 {
493         EditFace *efa, efatest;
494         
495         efatest.v1= v1;
496         efatest.v2= v2;
497         efatest.v3= v3;
498         efatest.v4= v4;
499         
500         efa= em->faces.first;
501         while(efa) {
502                 if(compareface_overlaps(&efatest, efa)) return efa;
503                 efa= efa->next;
504         }
505         return NULL;
506 }
507
508 /* will be new face smooth or solid? depends on smoothness of face neighbours
509  * of new face, if function return 1, then new face will be smooth, when functio
510  * will return zero, then new face will be solid */
511 static void fix_new_face(EditMesh *em, EditFace *eface)
512 {
513         struct EditFace *efa;
514         struct EditEdge *eed=NULL;
515         struct EditVert *v1 = eface->v1, *v2 = eface->v2, *v3 = eface->v3, *v4 = eface->v4;
516         struct EditVert *ev1=NULL, *ev2=NULL;
517         short smooth=0; /* "total smoothnes" of faces in neighbourhood */
518         short coef;     /* "weight" of smoothness */
519         short count=0;  /* number of edges with same direction as eface */
520         short vi00=0, vi01=0, vi10=0, vi11=0; /* vertex indexes */
521
522         efa = em->faces.first;
523
524         while(efa) {
525
526                 if(efa==eface) {
527                         efa = efa->next;
528                         continue;
529                 }
530
531                 coef = 0;
532                 ev1 = ev2 = NULL;
533                 eed = NULL;
534
535                 if(efa->v1==v1 || efa->v2==v1 || efa->v3==v1 || efa->v4==v1) {
536                         ev1 = v1;
537                         coef++;
538                 }
539                 if(efa->v1==v2 || efa->v2==v2 || efa->v3==v2 || efa->v4==v2) {
540                         if(ev1) ev2 = v2;
541                         else ev1 = v2;
542                         coef++;
543                 }
544                 if(efa->v1==v3 || efa->v2==v3 || efa->v3==v3 || efa->v4==v3) {
545                         if(coef<2) {
546                                 if(ev1) ev2 = v3;
547                                 else ev1 = v3;
548                         }
549                         coef++;
550                 }
551                 if((v4) && (efa->v1==v4 || efa->v2==v4 || efa->v3==v4 || efa->v4==v4)) {
552                         if(ev1 && coef<2) ev2 = v4;
553                         coef++;
554                 }
555
556                 /* "democracy" of smoothness */
557                 if(efa->flag & ME_SMOOTH)
558                         smooth += coef;
559                 else
560                         smooth -= coef;
561
562                 /* try to find edge using vertexes ev1 and ev2 */
563                 if((ev1) && (ev2) && (ev1!=ev2)) eed = findedgelist(em, ev1, ev2);
564
565                 /* has bordering edge of efa same direction as edge of eface ? */
566                 if(eed) {
567                         if(eed->v1==v1) vi00 = 1;
568                         else if(eed->v1==v2) vi00 = 2;
569                         else if(eed->v1==v3) vi00 = 3;
570                         else if(v4 && eed->v1==v4) vi00 = 4;
571
572                         if(eed->v2==v1) vi01 = 1;
573                         else if(eed->v2==v2) vi01 = 2;
574                         else if(eed->v2==v3) vi01 = 3;
575                         else if(v4 && eed->v2==v4) vi01 = 4;
576
577                         if(v4) {
578                                 if(vi01==1 && vi00==4) vi00 = 0;
579                                 if(vi01==4 && vi00==1) vi01 = 0;
580                         }
581                         else {
582                                 if(vi01==1 && vi00==3) vi00 = 0;
583                                 if(vi01==3 && vi00==1) vi01 = 0;
584                         }
585
586                         if(eed->v1==efa->v1) vi10 = 1;
587                         else if(eed->v1==efa->v2) vi10 = 2;
588                         else if(eed->v1==efa->v3) vi10 = 3;
589                         else if(efa->v4 && eed->v1==efa->v4) vi10 = 4;
590
591                         if(eed->v2==efa->v1) vi11 = 1;
592                         else if(eed->v2==efa->v2) vi11 = 2;
593                         else if(eed->v2==efa->v3) vi11 = 3;
594                         else if(efa->v4 && eed->v2==efa->v4) vi11 = 4;
595
596                         if(efa->v4) {
597                                 if(vi11==1 && vi10==4) vi10 = 0;
598                                 if(vi11==4 && vi10==1) vi11 = 0;
599                         }
600                         else {
601                                 if(vi11==1 && vi10==3) vi10 = 0;
602                                 if(vi11==3 && vi10==1) vi11 = 0;
603                         }
604
605                         if(((vi00>vi01) && (vi10>vi11)) ||
606                                 ((vi00<vi01) && (vi10<vi11)))
607                                 count++;
608                         else
609                                 count--;
610                 }
611
612                 efa = efa->next;
613         }
614
615         /* set up smoothness according voting of face in neighbourhood */
616         if(smooth >= 0)
617                 eface->flag |= ME_SMOOTH;
618         else
619                 eface->flag &= ~ME_SMOOTH;
620
621         /* flip face, when too much "face normals" in neighbourhood is different */
622         if(count > 0) {
623                 flipface(em, eface);
624         }
625 }
626
627 /* only adds quads or trias when there's edges already */
628 void addfaces_from_edgenet(EditMesh *em)
629 {
630         EditVert *eve1, *eve2, *eve3, *eve4;
631         
632         for(eve1= em->verts.first; eve1; eve1= eve1->next) {
633                 for(eve2= em->verts.first; (eve1->f & 1) && eve2; eve2= eve2->next) {
634                         if(findedgelist(em, eve1,eve2)) {
635                                 for(eve3= em->verts.first; (eve2->f & 1) && eve3; eve3= eve3->next) {
636                                         if((eve2!=eve3 && (eve3->f & 1) && findedgelist(em, eve1,eve3))) {
637                                                 EditEdge *sh_edge= NULL;
638                                                 EditVert *sh_vert= NULL;
639                                                 
640                                                 sh_edge= findedgelist(em, eve2,eve3);
641                                                 
642                                                 if(sh_edge) { /* Add a triangle */
643                                                         if(!exist_face_overlaps(em, eve1,eve2,eve3,NULL))
644                                                                 fix_new_face(em, addfacelist(em, eve1,eve2,eve3,NULL,NULL,NULL));
645                                                 }
646                                                 else { /* Check for a shared vertex */
647                                                         for(eve4= em->verts.first; eve4; eve4= eve4->next) {
648                                                                 if(eve4!=eve1 && eve4!=eve2 && eve4!=eve3 && (eve4->f & 1) &&
649                                                                    !findedgelist(em, eve1,eve4) && findedgelist(em, eve2,eve4) &&
650                                                                    findedgelist(em, eve3,eve4)) {
651                                                                         sh_vert= eve4;
652                                                                         break;
653                                                                 }
654                                                         }
655                                                         
656                                                         if(sh_vert) {
657                                                                 if(sh_vert) {
658                                                                         if(!exist_face_overlaps(em, eve1,eve2,eve4,eve3))
659                                                                                 fix_new_face(em, addfacelist(em, eve1,eve2,eve4,eve3,NULL,NULL));
660                                                                 }
661                                                         }
662                                                 }
663                                         }
664                                 }
665                         }
666                 }
667         }
668
669         EM_select_flush(em);
670         
671 // XXX  DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
672 }
673
674 static void addedgeface_mesh(Mesh *me, BMEditMesh *bem, wmOperator *op)
675 {
676         EditMesh *em;
677         EditVert *eve, *neweve[4];
678         EditEdge *eed;
679         EditFace *efa;
680         short amount=0;
681         
682         /*return if bmesh vert connect does anything.*/
683         if (bem->selectmode & SCE_SELECT_VERTEX) {
684                 BMesh *bm = bem->bm;
685                 BMOperator bmop;
686                 int len, ok;
687                 
688                 EDBM_InitOpf(bem, &bmop, op, "connectverts verts=%hv", BM_SELECT);
689                 BMO_Exec_Op(bem->bm, &bmop);
690
691                 len = BMO_GetSlot(&bmop, "edgeout")->len;               
692
693                 ok = EDBM_FinishOp(bem, &bmop, op, 1);
694                 if (!ok) return OPERATOR_CANCELLED;
695
696                 if (len) return;        
697         }
698
699         /*return if bmesh face dissolve finds stuff to
700           dissolve.  this entire tool should be
701           bmeshafied eventually, but until then
702           hacks like this to integrate with it
703           are necassary.*/
704         if (bem->selectmode & SCE_SELECT_VERTEX) {
705                 BMesh *bm = bem->bm;
706                 BMOperator bmop;
707                 int len, ok;
708                 
709                 EDBM_InitOpf(bem, &bmop, op, "dissolvefaces faces=%hf", BM_SELECT);
710                 BMO_Exec_Op(bem->bm, &bmop);
711
712                 len = BMO_GetSlot(&bmop, "regionout")->len;             
713                 
714                 ok = EDBM_FinishOp(bem, &bmop, op, 1);
715                 if (!ok) return OPERATOR_CANCELLED;
716
717                 if (len) return;        
718         }
719
720         em = BKE_mesh_get_editmesh(me);
721
722         /* how many selected ? */
723         if(em->selectmode & SCE_SELECT_EDGE) {
724                 /* in edge mode finding selected vertices means flushing down edge codes... */
725                 /* can't make face with only edge selection info... */
726                 EM_selectmode_set(em);
727         }
728         
729         for(eve= em->verts.first; eve; eve= eve->next) {
730                 if(eve->f & SELECT) {
731                         amount++;
732                         if(amount>4) break;                     
733                         neweve[amount-1]= eve;
734                 }
735         }
736
737         if(amount==2) {
738                 eed= addedgelist(em, neweve[0], neweve[1], NULL);
739                 EM_select_edge(eed, 1);
740                 
741                 BKE_mesh_end_editmesh(me, em);
742                 // XXX          DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); 
743                 return;
744         }
745         else if(amount > 4) {
746                 addfaces_from_edgenet(em);
747                 BKE_mesh_end_editmesh(me, em);
748                 return;
749         }
750         else if(amount<2) {
751                 BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make an edge/face");
752                 BKE_mesh_end_editmesh(me, em);
753                 return;
754         }
755
756         efa= NULL; // check later
757
758         if(amount==3) {
759                 
760                 if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], NULL)==0) {
761                         efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
762                         EM_select_face(efa, 1);
763                 }
764                 else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
765         }
766         else if(amount==4) {
767                 /* this test survives when theres 2 triangles */
768                 if(exist_face(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
769                         int tria= 0;
770                         
771                         /* remove trias if they exist, 4 cases.... */
772                         if(exist_face(em, neweve[0], neweve[1], neweve[2], NULL)) tria++;
773                         if(exist_face(em, neweve[0], neweve[1], neweve[3], NULL)) tria++;
774                         if(exist_face(em, neweve[0], neweve[2], neweve[3], NULL)) tria++;
775                         if(exist_face(em, neweve[1], neweve[2], neweve[3], NULL)) tria++;
776                 
777                         if(tria==2) join_triangles(em);
778                         else if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) {
779                                  /* If there are 4 Verts, But more selected edges, we need to call addfaces_from_edgenet */
780                                         EditEdge *eedcheck;
781                                         int count;
782                                         count = 0;
783                                         for(eedcheck= em->edges.first; eedcheck; eedcheck= eedcheck->next) {
784                                                 if(eedcheck->f & SELECT) {
785                                                         count++;
786                                                 }
787                                         }       
788                                 
789                                 if(count++ > 4){
790                                         addfaces_from_edgenet(em);
791                                         BKE_mesh_end_editmesh(me, em);
792                                         return;
793                                 } else {
794                                 /* if 4 edges exist, we just create the face, convex or not */
795                                         efa= addface_from_edges(em);
796                                         if(efa==NULL) {
797                                                 
798                                                 /* the order of vertices can be anything, 6 cases to check */
799                                                 if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
800                                                         efa= addfacelist(em, neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
801                                                 }
802                                                 else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
803                                                         efa= addfacelist(em, neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
804                                                 }
805                                                 else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
806                                                         efa= addfacelist(em, neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
807                                                 }
808                                                 else if( convex(neweve[0]->co, neweve[1]->co, neweve[3]->co, neweve[2]->co) ) {
809                                                         efa= addfacelist(em, neweve[0], neweve[1], neweve[3], neweve[2], NULL, NULL);
810                                                 }
811                                                 else if( convex(neweve[0]->co, neweve[3]->co, neweve[2]->co, neweve[1]->co) ) {
812                                                         efa= addfacelist(em, neweve[0], neweve[3], neweve[2], neweve[1], NULL, NULL);
813                                                 }
814                                                 else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) {
815                                                         efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL);
816                                                 }
817                                                 else printf("cannot find nice quad from concave set of vertices\n");
818                                         }
819                                 }
820                         }
821                         else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
822                 }
823                 else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face");
824         }
825         
826         if(efa) {
827                 EM_select_face(efa, 1);
828
829                 fix_new_face(em, efa);
830                 
831                 recalc_editnormals(em);
832         }
833
834         BKE_mesh_end_editmesh(me, em);
835 }
836
837 static int addedgeface_mesh_exec(bContext *C, wmOperator *op)
838 {
839         Object *obedit= CTX_data_edit_object(C);
840         BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
841         
842         addedgeface_mesh((Mesh *)obedit->data, em, op);
843         
844         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
845         
846         DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);     
847         
848         return OPERATOR_FINISHED;
849 }
850
851 void MESH_OT_edge_face_add(wmOperatorType *ot)
852 {
853         /* identifiers */
854         ot->name= "Make Edge/Face";
855         ot->idname= "MESH_OT_edge_face_add";
856         
857         /* api callbacks */
858         ot->exec= addedgeface_mesh_exec;
859         ot->poll= ED_operator_editmesh;
860         
861         /* flags */
862         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
863         
864 }
865
866
867
868 /* ************************ primitives ******************* */
869
870 // HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker
871 // this hack is only used so that scons+mingw + split-sources hack works
872         // ------------------------------- start copied code
873 /* these are not the monkeys you are looking for */
874 int monkeyo= 4;
875 int monkeynv= 271;
876 int monkeynf= 250;
877 signed char monkeyv[271][3]= {
878 {-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92},
879 {-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83},
880 {-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102},
881 {-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92},
882 {-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74},
883 {-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99},
884 {-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105},
885 {-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100},
886 {-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100},
887 {-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73},
888 {-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45},
889 {-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68},
890 {-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68},
891 {-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80},
892 {-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96},
893 {-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90},
894 {-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85},
895 {-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94},
896 {-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96},
897 {-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95},
898 {-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84},
899 {-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109},
900 {-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88},
901 {-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82},
902 {-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96},
903 {-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96},
904 {-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100},
905 {-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104},
906 {-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71},
907 {-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88},
908 {-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84},
909 {-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81},
910 {-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99},
911 {-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87},
912 {-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100},
913 {-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97},
914 {-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86},
915 {-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96},
916 {-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79},
917 {-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59},
918 {-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37},
919 {-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59},
920 {-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7},
921 {-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9},
922 {-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52},
923 {-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51},
924 {-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55},
925 {-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34},
926 {-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30},
927 {-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7},
928 {-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57},
929 {-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26},
930 {-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16},
931 {6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54},
932 {4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52},
933 {28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28},
934 {-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57},
935 {31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27},
936 {-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35},
937 {-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24},
938 {-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41},
939 {-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41},
940 {6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62},
941 {7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42},
942 {-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48},
943 {8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62},
944 {33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63},
945 {-26,-16,-42},{-17,49,-49},
946 };
947
948 signed char monkeyf[250][4]= {
949 {27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4}, 
950 {3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6}, 
951 {5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8}, 
952 {7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12}, 
953 {5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12}, 
954 {-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4}, 
955 {10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4}, 
956 {5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23}, 
957 {20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15}, 
958 {12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, 
959 {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, 
960 {18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44}, 
961 {24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19}, 
962 {16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38}, 
963 {8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39}, 
964 {16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42}, 
965 {19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16}, 
966 {13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32}, 
967 {-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35}, 
968 {34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21}, 
969 {1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11}, 
970 {35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38}, 
971 {-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39}, 
972 {33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34}, 
973 {8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34}, 
974 {-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36}, 
975 {-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27}, 
976 {-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42}, 
977 {25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34}, 
978 {25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26}, 
979 {23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35}, 
980 {-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35}, 
981 {-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58}, 
982 {40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52}, 
983 {-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49}, 
984 {43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24}, 
985 {-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100}, 
986 {-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24}, 
987 {-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110}, 
988 {6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48}, 
989 {17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43}, 
990 {35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6}, 
991 {-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30}, 
992 {4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5}, 
993 {-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13}, 
994 {-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30}, 
995 {-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31}, 
996 {30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35}, 
997 {32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27}, 
998 {25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23}, 
999 {11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35}, 
1000 {32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4}, 
1001 {-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35}, 
1002 {24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33}, 
1003 {24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35}, 
1004 {11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36}, 
1005 {35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39}, 
1006 {18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17}, 
1007 {24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19}, 
1008 {16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30}, 
1009 {-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30}, 
1010 {23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66}, 
1011 {-68,-67,24,-33}, 
1012 };
1013         // ------------------------------- end copied code
1014
1015
1016 #define PRIM_PLANE              0
1017 #define PRIM_CUBE               1
1018 #define PRIM_CIRCLE             4
1019 #define PRIM_CYLINDER   5
1020 #define PRIM_CONE               7
1021 #define PRIM_GRID               10
1022 #define PRIM_UVSPHERE   11
1023 #define PRIM_ICOSPHERE  12
1024 #define PRIM_MONKEY             13
1025
1026 static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg,
1027                 int subdiv, float dia, float depth, int ext, int fill)
1028 {
1029         /*
1030          * type - for the type of shape
1031          * dia - the radius for cone,sphere cylinder etc.
1032          * depth - 
1033          * ext - extrude
1034          * fill - end capping, and option to fill in circle
1035          * cent[3] - center of the data. 
1036          * */
1037         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
1038         EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
1039         float phi, phid, vec[3];
1040         float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0};
1041         short a, b;
1042         
1043         EM_clear_flag_all(em, SELECT);
1044
1045         phid= 2.0f*(float)M_PI/tot;
1046         phi= .25f*(float)M_PI;
1047
1048         switch(type) {
1049         case PRIM_GRID: /*  grid */
1050                 /* clear flags */
1051                 eve= em->verts.first;
1052                 while(eve) {
1053                         eve->f= 0;
1054                         eve= eve->next;
1055                 }
1056                 /* one segment first: the X axis */
1057                 phi= 1.0; 
1058                 phid= 2.0/((float)tot-1);
1059                 for(a=0;a<tot;a++) {
1060                         vec[0]= dia*phi;
1061                         vec[1]= - dia;
1062                         vec[2]= 0.0f;
1063                         Mat4MulVecfl(mat,vec);
1064                         eve= addvertlist(em, vec, NULL);
1065                         eve->f= 1+2+4;
1066                         if (a) {
1067                                 addedgelist(em, eve->prev, eve, NULL);
1068                         }
1069                         phi-=phid;
1070                 }
1071                 /* extrude and translate */
1072                 vec[0]= vec[2]= 0.0;
1073                 vec[1]= dia*phid;
1074                 Mat4Mul3Vecfl(mat, vec);
1075                 
1076                 for(a=0;a<seg-1;a++) {
1077                         extrudeflag_vert(obedit, em, 2, nor);   // nor unused
1078                         translateflag(em, 2, vec);
1079                 }
1080                 break;
1081         case PRIM_UVSPHERE: /*  UVsphere */
1082                 
1083                 /* clear all flags */
1084                 eve= em->verts.first;
1085                 while(eve) {
1086                         eve->f= 0;
1087                         eve= eve->next;
1088                 }
1089                 
1090                 /* one segment first */
1091                 phi= 0; 
1092                 phid/=2;
1093                 for(a=0; a<=tot; a++) {
1094                         vec[0]= dia*sin(phi);
1095                         vec[1]= 0.0;
1096                         vec[2]= dia*cos(phi);
1097                         eve= addvertlist(em, vec, NULL);
1098                         eve->f= 1+2+4;
1099                         if(a==0) v1= eve;
1100                         else addedgelist(em, eve->prev, eve, NULL);
1101                         phi+= phid;
1102                 }
1103                 
1104                 /* extrude and rotate */
1105                 phi= M_PI/seg;
1106                 q[0]= cos(phi);
1107                 q[3]= sin(phi);
1108                 q[1]=q[2]= 0;
1109                 QuatToMat3(q, cmat);
1110                 
1111                 for(a=0; a<seg; a++) {
1112                         extrudeflag_vert(obedit, em, 2, nor); // nor unused
1113                         rotateflag(em, 2, v1->co, cmat);
1114                 }
1115
1116                 removedoublesflag(em, 4, 0, 0.0001);
1117
1118                 /* and now do imat */
1119                 eve= em->verts.first;
1120                 while(eve) {
1121                         if(eve->f & SELECT) {
1122                                 Mat4MulVecfl(mat,eve->co);
1123                         }
1124                         eve= eve->next;
1125                 }
1126                 break;
1127         case PRIM_ICOSPHERE: /* Icosphere */
1128                 {
1129                         EditVert *eva[12];
1130                         EditEdge *eed;
1131                         
1132                         /* clear all flags */
1133                         eve= em->verts.first;
1134                         while(eve) {
1135                                 eve->f= 0;
1136                                 eve= eve->next;
1137                         }
1138                         dia/=200;
1139                         for(a=0;a<12;a++) {
1140                                 vec[0]= dia*icovert[a][0];
1141                                 vec[1]= dia*icovert[a][1];
1142                                 vec[2]= dia*icovert[a][2];
1143                                 eva[a]= addvertlist(em, vec, NULL);
1144                                 eva[a]->f= 1+2;
1145                         }
1146                         for(a=0;a<20;a++) {
1147                                 EditFace *evtemp;
1148                                 v1= eva[ icoface[a][0] ];
1149                                 v2= eva[ icoface[a][1] ];
1150                                 v3= eva[ icoface[a][2] ];
1151                                 evtemp = addfacelist(em, v1, v2, v3, 0, NULL, NULL);
1152                                 evtemp->e1->f = 1+2;
1153                                 evtemp->e2->f = 1+2;
1154                                 evtemp->e3->f = 1+2;
1155                         }
1156
1157                         dia*=200;
1158                         for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0,1,0);
1159                         /* and now do imat */
1160                         eve= em->verts.first;
1161                         while(eve) {
1162                                 if(eve->f & 2) {
1163                                         Mat4MulVecfl(mat,eve->co);
1164                                 }
1165                                 eve= eve->next;
1166                         }
1167                         
1168                         // Clear the flag 2 from the edges
1169                         for(eed=em->edges.first;eed;eed=eed->next){
1170                                 if(eed->f & 2){
1171                                            eed->f &= !2;
1172                                 }   
1173                         }
1174                 }
1175                 break;
1176         case PRIM_MONKEY: /* Monkey */
1177                 {
1178                         //extern int monkeyo, monkeynv, monkeynf;
1179                         //extern signed char monkeyf[][4];
1180                         //extern signed char monkeyv[][3];
1181                         EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv");
1182                         int i;
1183
1184                         for (i=0; i<monkeynv; i++) {
1185                                 float v[3];
1186                                 v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
1187                                 tv[i]= addvertlist(em, v, NULL);
1188                                 tv[i]->f |= SELECT;
1189                                 tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(em, v, NULL);
1190                                 tv[monkeynv+i]->f |= SELECT;
1191                         }
1192                         for (i=0; i<monkeynf; i++) {
1193                                 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);
1194                                 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);
1195                         }
1196
1197                         MEM_freeN(tv);
1198
1199                         /* and now do imat */
1200                         for(eve= em->verts.first; eve; eve= eve->next) {
1201                                 if(eve->f & SELECT) {
1202                                         Mat4MulVecfl(mat,eve->co);
1203                                 }
1204                         }
1205                         recalc_editnormals(em);
1206                 }
1207                 break;
1208         default: /* all types except grid, sphere... */
1209                 if(type==PRIM_CONE);
1210                 else if(ext==0) 
1211                         depth= 0.0f;
1212         
1213                 /* vertices */
1214                 vtop= vdown= v1= v2= 0;
1215                 for(b=0; b<=ext; b++) {
1216                         for(a=0; a<tot; a++) {
1217                                 
1218                                 vec[0]= dia*sin(phi);
1219                                 vec[1]= dia*cos(phi);
1220                                 vec[2]= b?depth:-depth;
1221                                 
1222                                 Mat4MulVecfl(mat, vec);
1223                                 eve= addvertlist(em, vec, NULL);
1224                                 eve->f= SELECT;
1225                                 if(a==0) {
1226                                         if(b==0) v1= eve;
1227                                         else v2= eve;
1228                                 }
1229                                 phi+=phid;
1230                         }
1231                 }
1232                         
1233                 /* center vertices */
1234                 /* type PRIM_CONE can only have 1 one side filled
1235                  * if the cone has no capping, dont add vtop */
1236                 if((fill && type>1) || type == PRIM_CONE) {
1237                         vec[0]= vec[1]= 0.0f;
1238                         vec[2]= -depth;
1239                         Mat4MulVecfl(mat, vec);
1240                         vdown= addvertlist(em, vec, NULL);
1241                         if((ext || type==PRIM_CONE) && fill) {
1242                                 vec[0]= vec[1]= 0.0f;
1243                                 vec[2]= depth;
1244                                 Mat4MulVecfl(mat,vec);
1245                                 vtop= addvertlist(em, vec, NULL);
1246                         }
1247                 } else {
1248                         vdown= v1;
1249                         vtop= v2;
1250                 }
1251                 if(vtop) vtop->f= SELECT;
1252                 if(vdown) vdown->f= SELECT;
1253         
1254                 /* top and bottom face */
1255                 if(fill || type==PRIM_CONE) {
1256                         if(tot==4 && (type==0 || type==1)) {
1257                                 v3= v1->next->next;
1258                                 if(ext) v4= v2->next->next;
1259                                 
1260                                 addfacelist(em, v3, v1->next, v1, v3->next, NULL, NULL);
1261                                 if(ext) addfacelist(em, v2, v2->next, v4, v4->next, NULL, NULL);
1262                                 
1263                         }
1264                         else {
1265                                 v3= v1;
1266                                 v4= v2;
1267                                 for(a=1; a<tot; a++) {
1268                                         addfacelist(em, vdown, v3, v3->next, 0, NULL, NULL);
1269                                         v3= v3->next;
1270                                         if(ext && fill) {
1271                                                 addfacelist(em, vtop, v4, v4->next, 0, NULL, NULL);
1272                                                 v4= v4->next;
1273                                         }
1274                                 }
1275                                 if(type>1) {
1276                                         addfacelist(em, vdown, v3, v1, 0, NULL, NULL);
1277                                         if(ext) addfacelist(em, vtop, v4, v2, 0, NULL, NULL);
1278                                 }
1279                         }
1280                 }
1281                 else if(type==PRIM_CIRCLE) {  /* we need edges for a circle */
1282                         v3= v1;
1283                         for(a=1;a<tot;a++) {
1284                                 addedgelist(em, v3, v3->next, NULL);
1285                                 v3= v3->next;
1286                         }
1287                         addedgelist(em, v3, v1, NULL);
1288                 }
1289                 /* side faces */
1290                 if(ext) {
1291                         v3= v1;
1292                         v4= v2;
1293                         for(a=1; a<tot; a++) {
1294                                 addfacelist(em, v3, v3->next, v4->next, v4, NULL, NULL);
1295                                 v3= v3->next;
1296                                 v4= v4->next;
1297                         }
1298                         addfacelist(em, v3, v1, v2, v4, NULL, NULL);
1299                 }
1300                 else if(type==PRIM_CONE && fill) {
1301                         /* add the bottom flat area of the cone
1302                          * if capping is disabled dont bother */
1303                         v3= v1;
1304                         for(a=1; a<tot; a++) {
1305                                 addfacelist(em, vtop, v3->next, v3, 0, NULL, NULL);
1306                                 v3= v3->next;
1307                         }
1308                         addfacelist(em, vtop, v1, v3, 0, NULL, NULL);
1309                 }
1310         }
1311         
1312         EM_stats_update(em);
1313         /* simple selection flush OK, based on fact it's a single model */
1314         EM_select_flush(em); /* flushes vertex -> edge -> face selection */
1315         
1316         if(type!=0 && type!=13)
1317                 righthandfaces(em, 1);  /* otherwise monkey has eyes in wrong direction */
1318
1319         BKE_mesh_end_editmesh(obedit->data, em);
1320 }
1321
1322
1323 /* uses context to figure out transform for primitive */
1324 /* returns standard diameter */
1325 static float new_primitive_matrix(bContext *C, float primmat[][4])
1326 {
1327         Object *obedit= CTX_data_edit_object(C);
1328         Scene *scene = CTX_data_scene(C);
1329         View3D *v3d =CTX_wm_view3d(C);
1330         RegionView3D *rv3d= CTX_wm_region_view3d(C);
1331         float *curs, mat[3][3], vmat[3][3], cmat[3][3], imat[3][3];
1332         
1333         Mat4One(primmat);
1334         
1335         if(rv3d)
1336                 Mat3CpyMat4(vmat, rv3d->viewmat);
1337         else
1338                 Mat3One(vmat);
1339         
1340         /* inverse transform for view and object */
1341         Mat3CpyMat4(mat, obedit->obmat);
1342         Mat3MulMat3(cmat, vmat, mat);
1343         Mat3Inv(imat, cmat);
1344         Mat4CpyMat3(primmat, imat);
1345
1346         /* center */
1347         curs= give_cursor(scene, v3d);
1348         VECCOPY(primmat[3], curs);
1349         Mat3Inv(imat, mat);
1350         Mat3MulVecfl(imat, primmat[3]);
1351         VECSUB(primmat[3], primmat[3], obedit->obmat[3]);
1352         
1353         if(v3d) return v3d->grid;
1354         return 1.0f;
1355 }
1356
1357 /* ********* add primitive operators ************* */
1358
1359 static int add_primitive_plane_exec(bContext *C, wmOperator *op)
1360 {
1361         Object *obedit= CTX_data_edit_object(C);
1362         float dia, mat[4][4];
1363         
1364         dia= new_primitive_matrix(C, mat);
1365         /* plane (diameter of 1.41 makes it unit size) */
1366         dia*= sqrt(2.0f);
1367         
1368         make_prim(obedit, PRIM_PLANE, mat, 4, 0, 0, dia, 0.0f, 0, 1);
1369         
1370         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1371         
1372         return OPERATOR_FINISHED;       
1373 }
1374
1375 void MESH_OT_primitive_plane_add(wmOperatorType *ot)
1376 {
1377         /* identifiers */
1378         ot->name= "Add Plane";
1379         ot->idname= "MESH_OT_primitive_plane_add";
1380         
1381         /* api callbacks */
1382         ot->exec= add_primitive_plane_exec;
1383         ot->poll= ED_operator_editmesh;
1384         
1385         /* flags */
1386         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1387 }
1388
1389 static int add_primitive_cube_exec(bContext *C, wmOperator *op)
1390 {
1391         Object *obedit= CTX_data_edit_object(C);
1392         float dia, mat[4][4];
1393         
1394         dia= new_primitive_matrix(C, mat);
1395         /* plane (diameter of 1.41 makes it unit size) */
1396         dia*= sqrt(2.0f);
1397         
1398         make_prim(obedit, PRIM_CUBE, mat, 4, 0, 0, dia, 1.0f, 1, 1);
1399         
1400         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1401         
1402         return OPERATOR_FINISHED;       
1403 }
1404
1405 void MESH_OT_primitive_cube_add(wmOperatorType *ot)
1406 {
1407         /* identifiers */
1408         ot->name= "Add Cube";
1409         ot->idname= "MESH_OT_primitive_cube_add";
1410         
1411         /* api callbacks */
1412         ot->exec= add_primitive_cube_exec;
1413         ot->poll= ED_operator_editmesh;
1414         
1415         /* flags */
1416         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1417 }
1418
1419 static int add_primitive_circle_exec(bContext *C, wmOperator *op)
1420 {
1421         Object *obedit= CTX_data_edit_object(C);
1422         float dia, mat[4][4];
1423         
1424         dia= new_primitive_matrix(C, mat);
1425         dia *= RNA_float_get(op->ptr,"radius");
1426         
1427         make_prim(obedit, PRIM_CIRCLE, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 0.0f, 0, 
1428                           RNA_boolean_get(op->ptr, "fill"));
1429         
1430         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1431         
1432         return OPERATOR_FINISHED;       
1433 }
1434
1435 void MESH_OT_primitive_circle_add(wmOperatorType *ot)
1436 {
1437         /* identifiers */
1438         ot->name= "Add Circle";
1439         ot->idname= "MESH_OT_primitive_circle_add";
1440         
1441         /* api callbacks */
1442         ot->exec= add_primitive_circle_exec;
1443         ot->poll= ED_operator_editmesh;
1444         
1445         /* flags */
1446         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1447         
1448         /* props */
1449         RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 3, 500);
1450         RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
1451         RNA_def_boolean(ot->srna, "fill", 0, "Fill", "");
1452 }
1453
1454 static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
1455 {
1456         Object *obedit= CTX_data_edit_object(C);
1457         float dia, mat[4][4];
1458         
1459         dia= new_primitive_matrix(C, mat);
1460         dia *= RNA_float_get(op->ptr, "radius");
1461         
1462         make_prim(obedit, PRIM_CYLINDER, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 
1463                           RNA_float_get(op->ptr, "depth"), 1, 1);
1464         
1465         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1466         
1467         return OPERATOR_FINISHED;       
1468 }
1469
1470 void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
1471 {
1472         /* identifiers */
1473         ot->name= "Add Cylinder";
1474         ot->idname= "MESH_OT_primitive_cylinder_add";
1475         
1476         /* api callbacks */
1477         ot->exec= add_primitive_cylinder_exec;
1478         ot->poll= ED_operator_editmesh;
1479         
1480         /* flags */
1481         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1482         
1483         /* props */
1484         RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
1485         RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
1486         RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
1487 }
1488
1489 static int add_primitive_tube_exec(bContext *C, wmOperator *op)
1490 {
1491         Object *obedit= CTX_data_edit_object(C);
1492         float dia, mat[4][4];
1493         
1494         dia= new_primitive_matrix(C, mat);
1495         dia *= RNA_float_get(op->ptr, "radius");
1496         
1497         make_prim(obedit, PRIM_CYLINDER, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 
1498                           RNA_float_get(op->ptr, "depth"), 1, 0);
1499         
1500         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1501         
1502         return OPERATOR_FINISHED;       
1503 }
1504
1505 void MESH_OT_primitive_tube_add(wmOperatorType *ot)
1506 {
1507         /* identifiers */
1508         ot->name= "Add Tube";
1509         ot->idname= "MESH_OT_primitive_tube_add";
1510         
1511         /* api callbacks */
1512         ot->exec= add_primitive_tube_exec;
1513         ot->poll= ED_operator_editmesh;
1514         
1515         /* flags */
1516         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1517         
1518         /* props */
1519         RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
1520         RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
1521         RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
1522 }
1523
1524 static int add_primitive_cone_exec(bContext *C, wmOperator *op)
1525 {
1526         Object *obedit= CTX_data_edit_object(C);
1527         float dia, mat[4][4];
1528         
1529         dia= new_primitive_matrix(C, mat);
1530         dia *= RNA_float_get(op->ptr, "radius");
1531         
1532         make_prim(obedit, PRIM_CONE, mat, RNA_int_get(op->ptr, "vertices"), 0, 0, dia, 
1533                           RNA_float_get(op->ptr, "depth"), 0, RNA_boolean_get(op->ptr, "cap_end"));
1534         
1535         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1536         
1537         return OPERATOR_FINISHED;       
1538 }
1539
1540 void MESH_OT_primitive_cone_add(wmOperatorType *ot)
1541 {
1542         /* identifiers */
1543         ot->name= "Add Cone";
1544         ot->idname= "MESH_OT_primitive_cone_add";
1545         
1546         /* api callbacks */
1547         ot->exec= add_primitive_cone_exec;
1548         ot->poll= ED_operator_editmesh;
1549         
1550         /* flags */
1551         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1552         
1553         /* props */
1554         RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
1555         RNA_def_float(ot->srna, "radius", 1.0f, -FLT_MAX, FLT_MAX, "Radius", "", 0.001, 100.00);
1556         RNA_def_float(ot->srna, "depth", 1.0f, -FLT_MAX, FLT_MAX, "Depth", "", 0.001, 100.00);
1557         RNA_def_boolean(ot->srna, "cap_end", 0, "Cap End", "");
1558
1559 }
1560
1561 static int add_primitive_grid_exec(bContext *C, wmOperator *op)
1562 {
1563         Object *obedit= CTX_data_edit_object(C);
1564         float dia, mat[4][4];
1565         
1566         dia= new_primitive_matrix(C, mat);
1567         dia*= RNA_float_get(op->ptr, "size");
1568         
1569         make_prim(obedit, PRIM_GRID, mat, RNA_int_get(op->ptr, "x_subdivisions"), 
1570                           RNA_int_get(op->ptr, "y_subdivisions"), 0, dia, 0.0f, 0, 1);
1571         
1572         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1573         
1574         return OPERATOR_FINISHED;       
1575 }
1576
1577 void MESH_OT_primitive_grid_add(wmOperatorType *ot)
1578 {
1579         /* identifiers */
1580         ot->name= "Add Grid";
1581         ot->idname= "MESH_OT_primitive_grid_add";
1582         
1583         /* api callbacks */
1584         ot->exec= add_primitive_grid_exec;
1585         ot->poll= ED_operator_editmesh;
1586         
1587         /* flags */
1588         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1589         
1590         /* props */
1591         RNA_def_int(ot->srna, "x_subdivisions", 10, INT_MIN, INT_MAX, "X Subdivisions", "", 3, 1000);
1592         RNA_def_int(ot->srna, "y_subdivisions", 10, INT_MIN, INT_MAX, "Y Subdivisons", "", 3, 1000);
1593         RNA_def_float(ot->srna, "size", 1.0f, -FLT_MAX, FLT_MAX, "Size", "", 0.001, FLT_MAX);
1594 }
1595
1596 static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
1597 {
1598         Object *obedit= CTX_data_edit_object(C);
1599         float mat[4][4];
1600         
1601         new_primitive_matrix(C, mat);
1602         
1603         make_prim(obedit, PRIM_MONKEY, mat, 0, 0, 2, 0.0f, 0.0f, 0, 0);
1604         
1605         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1606         
1607         return OPERATOR_FINISHED;       
1608 }
1609
1610 void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
1611 {
1612         /* identifiers */
1613         ot->name= "Add Monkey";
1614         ot->idname= "MESH_OT_primitive_monkey_add";
1615         
1616         /* api callbacks */
1617         ot->exec= add_primitive_monkey_exec;
1618         ot->poll= ED_operator_editmesh;
1619         
1620         /* flags */
1621         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1622 }
1623
1624 static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
1625 {
1626         Object *obedit= CTX_data_edit_object(C);
1627         float dia, mat[4][4];
1628         
1629         dia= new_primitive_matrix(C, mat);
1630         dia*= RNA_float_get(op->ptr, "size");
1631
1632         make_prim(obedit, PRIM_UVSPHERE, mat, RNA_int_get(op->ptr, "rings"), 
1633                           RNA_int_get(op->ptr, "segments"), 0, dia, 0.0f, 0, 0);
1634         
1635         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1636         
1637         return OPERATOR_FINISHED;       
1638 }
1639
1640 void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
1641 {
1642         /* identifiers */
1643         ot->name= "Add UV Sphere";
1644         ot->idname= "MESH_OT_primitive_uv_sphere_add";
1645         
1646         /* api callbacks */
1647         ot->exec= add_primitive_uvsphere_exec;
1648         ot->poll= ED_operator_editmesh;
1649         
1650         /* flags */
1651         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1652         
1653         /* props */
1654         RNA_def_int(ot->srna, "segments", 32, INT_MIN, INT_MAX, "Segments", "", 3, 500);
1655         RNA_def_int(ot->srna, "rings", 24, INT_MIN, INT_MAX, "Rings", "", 3, 500);
1656         RNA_def_float(ot->srna, "size", 1.0f, -FLT_MAX, FLT_MAX, "Size", "", 0.001, 100.00);
1657 }
1658
1659 static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
1660 {
1661         Object *obedit= CTX_data_edit_object(C);
1662         float dia, mat[4][4];
1663         
1664         dia= new_primitive_matrix(C, mat);
1665         dia*= RNA_float_get(op->ptr, "size");
1666         
1667         make_prim(obedit, PRIM_ICOSPHERE, mat, 0, 0, 
1668                           RNA_int_get(op->ptr, "subdivisions"), dia, 0.0f, 0, 0);
1669         
1670         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1671         
1672         return OPERATOR_FINISHED;       
1673 }
1674
1675 void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
1676 {
1677         /* identifiers */
1678         ot->name= "Add Ico Sphere";
1679         ot->idname= "MESH_OT_primitive_ico_sphere_add";
1680         
1681         /* api callbacks */
1682         ot->exec= add_primitive_icosphere_exec;
1683         ot->poll= ED_operator_editmesh;
1684         
1685         /* flags */
1686         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1687         
1688         /* props */
1689         RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8);
1690         RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
1691 }
1692