rename operators TFM_OT_* --> TRANSFORM_OT_*
[blender.git] / source / blender / editors / mesh / editmesh_loop.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
32 editmesh_loop: tools with own drawing subloops, select, knife, subdiv
33
34 */
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <math.h>
39
40 #include "MEM_guardedalloc.h"
41
42
43 #include "DNA_mesh_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_view3d_types.h"
49 #include "DNA_windowmanager_types.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_math.h"
53 #include "BLI_editVert.h"
54 #include "BLI_ghash.h"
55
56 #include "BKE_context.h"
57 #include "BKE_depsgraph.h"
58 #include "BKE_displist.h"
59 #include "BKE_global.h"
60 #include "BKE_library.h"
61 #include "BKE_mesh.h"
62 #include "BKE_object.h"
63 #include "BKE_report.h"
64 #include "BKE_utildefines.h"
65
66 #include "PIL_time.h"
67
68 #include "BIF_gl.h"
69
70 #include "RNA_access.h"
71 #include "RNA_define.h"
72
73 #include "WM_api.h"
74 #include "WM_types.h"
75
76 #include "ED_mesh.h"
77 #include "ED_screen.h"
78 #include "ED_view3d.h"
79
80 #include "mesh_intern.h"
81
82 /* **** XXX ******** */
83 static void BIF_undo_push() {}
84 static void BIF_undo() {}
85 static void error() {}
86 static int qtest() {return 0;}
87 /* **** XXX ******** */
88
89
90 /* New LoopCut */
91 static void edgering_sel(EditMesh *em, EditEdge *startedge, int select, int previewlines)
92 {
93         EditEdge *eed;
94         EditFace *efa;
95         EditVert *v[2][2];
96         float co[2][3];
97         int looking= 1,i;
98         
99         /* in eed->f1 we put the valence (amount of faces in edge) */
100         /* in eed->f2 we put tagged flag as correct loop */
101         /* in efa->f1 we put tagged flag as correct to select */
102
103         for(eed= em->edges.first; eed; eed= eed->next) {
104                 eed->f1= 0;
105                 eed->f2= 0;
106         }
107         for(efa= em->faces.first; efa; efa= efa->next) {
108                 efa->f1= 0;
109                 if(efa->h==0) {
110                         efa->e1->f1++;
111                         efa->e2->f1++;
112                         efa->e3->f1++;
113                         if(efa->e4) efa->e4->f1++;
114                 }
115         }
116         
117         // tag startedge OK
118         startedge->f2= 1;
119         
120         while(looking) {
121                 looking= 0;
122                 
123                 for(efa= em->faces.first; efa; efa= efa->next) {
124                         if(efa->e4 && efa->f1==0 && efa->h == 0) {      // not done quad
125                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
126
127                                         // if edge tagged, select opposing edge and mark face ok
128                                         if(efa->e1->f2) {
129                                                 efa->e3->f2= 1;
130                                                 efa->f1= 1;
131                                                 looking= 1;
132                                         }
133                                         else if(efa->e2->f2) {
134                                                 efa->e4->f2= 1;
135                                                 efa->f1= 1;
136                                                 looking= 1;
137                                         }
138                                         if(efa->e3->f2) {
139                                                 efa->e1->f2= 1;
140                                                 efa->f1= 1;
141                                                 looking= 1;
142                                         }
143                                         if(efa->e4->f2) {
144                                                 efa->e2->f2= 1;
145                                                 efa->f1= 1;
146                                                 looking= 1;
147                                         }
148                                 }
149                         }
150                 }
151         }
152         
153         if(previewlines > 0 && select == 0){
154 // XXX                  persp(PERSP_VIEW);
155 // XXX                  glPushMatrix();
156 // XXX                  mymultmatrix(obedit->obmat);
157
158                         for(efa= em->faces.first; efa; efa= efa->next) {
159                                 if(efa->v4 == NULL) {  continue; }
160                                 if(efa->h == 0){
161                                         if(efa->e1->f2 == 1){
162                                                 if(efa->e1->h == 1 || efa->e3->h == 1 )
163                                                         continue;
164                                                 
165                                                 v[0][0] = efa->v1;
166                                                 v[0][1] = efa->v2;
167                                                 v[1][0] = efa->v4;
168                                                 v[1][1] = efa->v3;
169                                         } else if(efa->e2->f2 == 1){
170                                                 if(efa->e2->h == 1 || efa->e4->h == 1)
171                                                         continue;
172                                                 v[0][0] = efa->v2;
173                                                 v[0][1] = efa->v3;
174                                                 v[1][0] = efa->v1;
175                                                 v[1][1] = efa->v4;                                      
176                                         } else { continue; }
177                                                                                   
178                                         for(i=1;i<=previewlines;i++){
179                                                 co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
180                                                 co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
181                                                 co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
182
183                                                 co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
184                                                 co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
185                                                 co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];                                        
186                                                 glColor3ub(255, 0, 255);
187                                                 glBegin(GL_LINES);      
188                                                 glVertex3f(co[0][0],co[0][1],co[0][2]);
189                                                 glVertex3f(co[1][0],co[1][1],co[1][2]);
190                                                 glEnd();
191                                         }
192                                 }
193                         }
194                         glPopMatrix();   
195         } else {        
196         
197         /* (de)select the edges */
198                 for(eed= em->edges.first; eed; eed= eed->next) {
199                 if(eed->f2) EM_select_edge(eed, select);
200                 }
201         }
202 }
203
204 void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
205 {
206         ViewContext vc; // XXX
207         EditEdge *nearest=NULL, *eed;
208         float fac;
209         int keys = 0, holdnum=0, selectmode, dist;
210         short mvalo[2] = {0, 0}, mval[2] = {0, 0};
211         short event=0, val, choosing=1, cancel=0, cuthalf = 0, smooth=0;
212         short hasHidden = 0;
213         char msg[128];
214         
215         selectmode = em->selectmode;
216                 
217         if(em->selectmode & SCE_SELECT_FACE){
218                 em->selectmode =  SCE_SELECT_EDGE;
219                 EM_selectmode_set(em);    
220         }
221         
222         
223         BIF_undo_push("Loopcut Begin");
224         while(choosing && !cancel){
225 // XXX          getmouseco_areawin(mval);
226                 if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) {
227                         mvalo[0] = mval[0];
228                         mvalo[1] = mval[1];
229                         dist= 50;
230                         nearest = findnearestedge(&vc, &dist);  // returns actual distance in dist
231 //                      scrarea_do_windraw(curarea);    // after findnearestedge, backbuf!
232                         
233                         sprintf(msg,"Number of Cuts: %d",numcuts);
234                         if(smooth){
235                                 sprintf(msg,"%s (S)mooth: on",msg);
236                         } else {
237                                 sprintf(msg,"%s (S)mooth: off",msg);
238                         }
239                         
240 //                      headerprint(msg);
241                         /* Need to figure preview */
242                         if(nearest){
243                                 edgering_sel(em, nearest, 0, numcuts);
244                          }   
245 // XXX                  screen_swapbuffers();
246                         
247                 /* backbuffer refresh for non-apples (no aux) */
248 #ifndef __APPLE__
249 // XXX                  if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
250 //                              backdrawview3d(0);
251 //                      }
252 #endif
253                 }
254                 else PIL_sleep_ms(10);  // idle
255                 
256                 
257                 while(qtest()) 
258                 {
259                         val=0;
260 // XXX                  event= extern_qread(&val);
261                         if(val && (event ==  MOUSEX || event == MOUSEY)){ ; } 
262                         else if(val && ((event==LEFTMOUSE || event==RETKEY) || (event == MIDDLEMOUSE || event==PADENTER)))
263                         {
264                                 if(event == MIDDLEMOUSE){
265                                         cuthalf = 1;
266                                 }
267                                 if (nearest==NULL)
268                                         cancel = 1;
269                                 choosing=0;
270                                 mvalo[0] = -1;
271                         }
272                         else if(val && (event==ESCKEY || event==RIGHTMOUSE ))
273                         {
274                                 choosing=0;
275                                 cancel = 1;
276                                 mvalo[0] = -1;
277                         }
278                         else if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE))
279                         {
280                                 numcuts++;
281                                 mvalo[0] = -1;
282                         }
283                         else if(val && (event==PADMINUS || event==WHEELDOWNMOUSE))
284                         {
285                                 if(numcuts > 1){
286                                         numcuts--;
287                                         mvalo[0] = -1;
288                                 } 
289                         }
290                         else if(val && event==SKEY)
291                         {
292                                 if(smooth){smooth=0;} 
293                                 else { smooth=1; }
294                                 mvalo[0] = -1;
295                         }
296                         
297                         else if(val){
298                                 holdnum = -1;
299                                 switch(event){
300                                         case PAD9:
301                                         case NINEKEY:
302                                                 holdnum = 9; break;
303                                         case PAD8:
304                                         case EIGHTKEY:
305                                                 holdnum = 8;break;
306                                         case PAD7:
307                                         case SEVENKEY:
308                                                 holdnum = 7;break;
309                                         case PAD6:
310                                         case SIXKEY:
311                                                 holdnum = 6;break;
312                                         case PAD5:
313                                         case FIVEKEY:
314                                                 holdnum = 5;break;
315                                         case PAD4:
316                                         case FOURKEY:
317                                                 holdnum = 4;break;
318                                         case PAD3:
319                                         case THREEKEY:
320                                                 holdnum = 3; break;
321                                         case PAD2:
322                                         case TWOKEY:
323                                                 holdnum = 2;break;
324                                         case PAD1:
325                                         case ONEKEY:
326                                                 holdnum = 1; break;
327                                         case PAD0:
328                                         case ZEROKEY:
329                                                 holdnum = 0;break;      
330                                         case BACKSPACEKEY:
331                                                 holdnum = -2;break;                     
332                                 }
333                                 if(holdnum >= 0 && numcuts*10 < 130){
334                                         if(keys == 0){  // first level numeric entry
335                                                         if(holdnum > 0){
336                                                                         numcuts = holdnum;
337                                                                         keys++;         
338                                                         }
339                                         } else if(keys > 0){//highrt level numeric entry
340                                                         numcuts *= 10;
341                                                         numcuts += holdnum;
342                                                         keys++;         
343                                         }
344                                 } else if (holdnum == -2){// backspace
345                                         if (keys > 1){
346                                                 numcuts /= 10;          
347                                                 keys--;
348                                         } else {
349                                                 numcuts=1;
350                                                 keys = 0;
351                                         }
352                                 }
353                                 mvalo[0] = -1;
354                                 break;
355                         }  // End Numeric Entry                                         
356                 }  //End while(qtest())
357         }   // End Choosing
358
359         if(cancel){
360                 return;   
361         }
362         /* clean selection */
363         for(eed=em->edges.first; eed; eed = eed->next){
364                 EM_select_edge(eed,0);
365         }
366         /* select edge ring */
367         edgering_sel(em, nearest, 1, 0);
368         
369         /* now cut the loops */
370         if(smooth){
371                 fac= 1.0f;
372 // XXX          if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return;
373                 fac= 0.292f*fac;                        
374                 esubdivideflag(obedit, em, SELECT,fac,0,B_SMOOTH,numcuts,SUBDIV_SELECT_LOOPCUT);
375         } else {
376                 esubdivideflag(obedit, em, SELECT,0,0,0,numcuts,SUBDIV_SELECT_LOOPCUT);
377         }
378         /* if this was a single cut, enter edgeslide mode */
379         if(numcuts == 1 && hasHidden == 0){
380                 if(cuthalf)
381                         EdgeSlide(em, op, 1,0.0);
382                 else {
383                         if(EdgeSlide(em, op, 0,0.0) == -1){
384                                 BIF_undo();
385                         }
386                 }
387         }
388         
389         if(em->selectmode !=  selectmode){
390                 em->selectmode = selectmode;
391                 EM_selectmode_set(em);
392         }       
393         
394 //      DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
395         return;
396 }
397
398
399 /* *************** LOOP SELECT ************* */
400 #if 0
401 static short edgeFaces(EditMesh *em, EditEdge *e)
402 {
403         EditFace *search=NULL;
404         short count = 0;
405         
406         search = em->faces.first;
407         while(search){
408                 if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) 
409                         count++;
410                 search = search->next;
411         }
412         return count;   
413 }
414 #endif
415
416
417
418 /*   ***************** TRAIL ************************
419
420 Read a trail of mouse coords and return them as an array of CutCurve structs
421 len returns number of mouse coords read before commiting with RETKEY   
422 It is up to the caller to free the block when done with it,
423
424 XXX Is only used here, so local inside this file (ton)
425  */
426
427 #define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
428 #define TRAIL_FREEHAND 2
429 #define TRAIL_MIXED    3 /* (1|2) */
430 #define TRAIL_AUTO     4 
431 #define TRAIL_MIDPOINTS 8
432
433 typedef struct CutCurve {
434         float  x; 
435         float  y;
436 } CutCurve;
437
438
439 /* ******************************************************************** */
440 /* Knife Subdivide Tool.  Subdivides edges intersected by a mouse trail
441         drawn by user.
442         
443         Currently mapped to KKey when in MeshEdit mode.
444         Usage:
445                 Hit Shift K, Select Centers or Exact
446                 Hold LMB down to draw path, hit RETKEY.
447                 ESC cancels as expected.
448    
449         Contributed by Robert Wenzlaff (Det. Thorn).
450
451     2.5 revamp:
452     - non modal (no menu before cutting)
453     - exit on mouse release
454     - polygon/segment drawing can become handled by WM cb later
455
456 */
457
458 #define KNIFE_EXACT             1
459 #define KNIFE_MIDPOINT  2
460 #define KNIFE_MULTICUT  3
461
462 static EnumPropertyItem knife_items[]= {
463         {KNIFE_EXACT, "EXACT", 0, "Exact", ""},
464         {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""},
465         {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""},
466         {0, NULL, 0, NULL, NULL}
467 };
468
469 /* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */
470
471 static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct GHash *gh)
472 {
473 #define MAXSLOPE 100000
474         float  x11, y11, x12=0, y12=0, x2max, x2min, y2max;
475         float  y2min, dist, lastdist=0, xdiff2, xdiff1;
476         float  m1, b1, m2, b2, x21, x22, y21, y22, xi;
477         float  yi, x1min, x1max, y1max, y1min, perc=0; 
478         float  *scr;
479         float  threshold;
480         int  i;
481         
482         threshold = 0.000001; /*tolerance for vertex intersection*/
483         // XXX  threshold = scene->toolsettings->select_thresh / 100;
484         
485         /* Get screen coords of verts */
486         scr = BLI_ghash_lookup(gh, e->v1);
487         x21=scr[0];
488         y21=scr[1];
489         
490         scr = BLI_ghash_lookup(gh, e->v2);
491         x22=scr[0];
492         y22=scr[1];
493         
494         xdiff2=(x22-x21);  
495         if (xdiff2) {
496                 m2=(y22-y21)/xdiff2;
497                 b2= ((x22*y21)-(x21*y22))/xdiff2;
498         }
499         else {
500                 m2=MAXSLOPE;  /* Verticle slope  */
501                 b2=x22;      
502         }
503         
504         /*check for *exact* vertex intersection first*/
505         if(mode!=KNIFE_MULTICUT){
506                 for (i=0; i<len; i++){
507                         if (i>0){
508                                 x11=x12;
509                                 y11=y12;
510                         }
511                         else {
512                                 x11=c[i].x;
513                                 y11=c[i].y;
514                         }
515                         x12=c[i].x;
516                         y12=c[i].y;
517                         
518                         /*test e->v1*/
519                         if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){
520                                 e->v1->f1 = 1;
521                                 perc = 0;
522                                 return(perc);
523                         }
524                         /*test e->v2*/
525                         else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){
526                                 e->v2->f1 = 1;
527                                 perc = 0;
528                                 return(perc);
529                         }
530                 }
531         }
532         
533         /*now check for edge interesect (may produce vertex intersection as well)*/
534         for (i=0; i<len; i++){
535                 if (i>0){
536                         x11=x12;
537                         y11=y12;
538                 }
539                 else {
540                         x11=c[i].x;
541                         y11=c[i].y;
542                 }
543                 x12=c[i].x;
544                 y12=c[i].y;
545                 
546                 /* Perp. Distance from point to line */
547                 if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */
548                         /* change in sign.  Skip extra math */  
549                 else dist=x22-x12;      
550                 
551                 if (i==0) lastdist=dist;
552                 
553                 /* if dist changes sign, and intersect point in edge's Bound Box*/
554                 if ((lastdist*dist)<=0){
555                         xdiff1=(x12-x11); /* Equation of line between last 2 points */
556                         if (xdiff1){
557                                 m1=(y12-y11)/xdiff1;
558                                 b1= ((x12*y11)-(x11*y12))/xdiff1;
559                         }
560                         else{
561                                 m1=MAXSLOPE;
562                                 b1=x12;
563                         }
564                         x2max=MAX2(x21,x22)+0.001; /* prevent missed edges   */
565                         x2min=MIN2(x21,x22)-0.001; /* due to round off error */
566                         y2max=MAX2(y21,y22)+0.001;
567                         y2min=MIN2(y21,y22)-0.001;
568                         
569                         /* Found an intersect,  calc intersect point */
570                         if (m1==m2){ /* co-incident lines */
571                                 /* cut at 50% of overlap area*/
572                                 x1max=MAX2(x11, x12);
573                                 x1min=MIN2(x11, x12);
574                                 xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0;  
575                                 
576                                 y1max=MAX2(y11, y12);
577                                 y1min=MIN2(y11, y12);
578                                 yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0;
579                         }                       
580                         else if (m2==MAXSLOPE){ 
581                                 xi=x22;
582                                 yi=m1*x22+b1;
583                         }
584                         else if (m1==MAXSLOPE){ 
585                                 xi=x12;
586                                 yi=m2*x12+b2;
587                         }
588                         else {
589                                 xi=(b1-b2)/(m2-m1);
590                                 yi=(b1*m2-m1*b2)/(m2-m1);
591                         }
592                         
593                         /* Intersect inside bounding box of edge?*/
594                         if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){
595                                 /*test for vertex intersect that may be 'close enough'*/
596                                 if(mode!=KNIFE_MULTICUT){
597                                         if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){
598                                                 if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){
599                                                         e->v1->f1 = 1;
600                                                         perc = 0;
601                                                         break;
602                                                 }
603                                         }
604                                         if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){
605                                                 if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){
606                                                         e->v2->f1 = 1;
607                                                         perc = 0;
608                                                         break;
609                                                 }
610                                         }
611                                 }
612                                 if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21);   
613                                 else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/
614                                 //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
615                                 
616                                 break;
617                         }
618                 }       
619                 lastdist=dist;
620         }
621         return(perc);
622
623
624
625 #define MAX_CUTS 256
626
627 static int knife_cut_exec(bContext *C, wmOperator *op)
628 {
629         Object *obedit= CTX_data_edit_object(C);
630         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
631         ARegion *ar= CTX_wm_region(C);
632         EditEdge *eed;
633         EditVert *eve;
634         CutCurve curve[MAX_CUTS];
635         struct GHash *gh;
636         float isect=0.0;
637         float  *scr, co[4];
638         int len=0;
639         short numcuts=1, mode= RNA_int_get(op->ptr, "type");
640         
641         /* edit-object needed for matrix, and ar->regiondata for projections to work */
642         if (ELEM3(NULL, obedit, ar, ar->regiondata))
643                 return OPERATOR_CANCELLED;
644         
645         if (EM_nvertices_selected(em) < 2) {
646                 error("No edges are selected to operate on");
647                 BKE_mesh_end_editmesh(obedit->data, em);
648                 return OPERATOR_CANCELLED;;
649         }
650
651         /* get the cut curve */
652         RNA_BEGIN(op->ptr, itemptr, "path") {
653                 
654                 RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]);
655                 len++;
656                 if(len>= MAX_CUTS) break;
657         }
658         RNA_END;
659         
660         if(len<2) {
661                 BKE_mesh_end_editmesh(obedit->data, em);
662                 return OPERATOR_CANCELLED;
663         }
664
665         /*store percentage of edge cut for KNIFE_EXACT here.*/
666         for(eed=em->edges.first; eed; eed= eed->next) 
667                 eed->tmp.fp = 0.0; 
668         
669         /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/
670         gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
671         for(eve=em->verts.first; eve; eve=eve->next){
672                 scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates");
673                 VECCOPY(co, eve->co);
674                 co[3]= 1.0;
675                 mul_m4_v4(obedit->obmat, co);
676                 project_float(ar, co, scr);
677                 BLI_ghash_insert(gh, eve, scr);
678                 eve->f1 = 0; /*store vertex intersection flag here*/
679         
680         }
681         
682         eed= em->edges.first;           
683         while(eed) {    
684                 if( eed->v1->f & eed->v2->f & SELECT ){         // NOTE: uses vertex select, subdiv doesnt do edges yet
685                         isect= seg_intersect(eed, curve, len, mode, gh);
686                         if (isect!=0.0f) eed->f2= 1;
687                         else eed->f2=0;
688                         eed->tmp.fp= isect;
689                         //printf("isect=%i\n", isect);
690                 }
691                 else {
692                         eed->f2=0;
693                         eed->f1=0;
694                 }
695                 eed= eed->next;
696         }
697         
698         if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG);
699         else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG);
700         else esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG);
701
702         eed=em->edges.first;
703         while(eed){
704                 eed->f2=0;
705                 eed->f1=0;
706                 eed=eed->next;
707         }       
708         
709         BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
710         
711         BKE_mesh_end_editmesh(obedit->data, em);
712
713         DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
714         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
715
716         return OPERATOR_FINISHED;
717 }
718
719
720 void MESH_OT_knife_cut(wmOperatorType *ot)
721 {
722         PropertyRNA *prop;
723         
724         ot->name= "Knife Cut";
725         ot->description= "Cut selected edges and faces into parts.";
726         ot->idname= "MESH_OT_knife_cut";
727         
728         ot->invoke= WM_gesture_lines_invoke;
729         ot->modal= WM_gesture_lines_modal;
730         ot->exec= knife_cut_exec;
731         
732         ot->poll= EM_view3d_poll;
733         
734         /* flags */
735         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
736         
737         RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", "");
738         prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
739         RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
740         
741         /* internal */
742         RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
743 }
744
745 /* ******************************************************* */
746