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