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