Blender  V2.59
editmesh_loop.c
Go to the documentation of this file.
00001 /*
00002  * $Id: editmesh_loop.c 38081 2011-07-04 11:28:39Z ton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2004 by Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 /*
00036 
00037 editmesh_loop: tools with own drawing subloops, select, knife, subdiv
00038 
00039 */
00040 
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <math.h>
00044 
00045 #include "MEM_guardedalloc.h"
00046 
00047 
00048 #include "DNA_object_types.h"
00049 #include "DNA_scene_types.h"
00050 #include "DNA_screen_types.h"
00051 
00052 #include "BLI_blenlib.h"
00053 #include "BLI_math.h"
00054 #include "BLI_utildefines.h"
00055 #include "BLI_editVert.h"
00056 #include "BLI_ghash.h"
00057 
00058 #include "BKE_context.h"
00059 #include "BKE_depsgraph.h"
00060 #include "BKE_mesh.h"
00061 #include "BKE_array_mallocn.h"
00062 
00063 #include "PIL_time.h"
00064 
00065 #include "BIF_gl.h"
00066 
00067 #include "RNA_access.h"
00068 #include "RNA_define.h"
00069 
00070 #include "WM_api.h"
00071 #include "WM_types.h"
00072 
00073 #include "ED_mesh.h"
00074 #include "ED_view3d.h"
00075 
00076 #include "mesh_intern.h"
00077 
00078 /* **** XXX ******** */
00079 static void error(const char *UNUSED(arg)) {}
00080 /* **** XXX ******** */
00081 
00082 #if 0 /* UNUSED 2.5 */
00083 static void edgering_sel(EditMesh *em, EditEdge *startedge, int select, int previewlines)
00084 {
00085         EditEdge *eed;
00086         EditFace *efa;
00087         EditVert *v[2][2];
00088         float co[2][3];
00089         int looking= 1,i;
00090         
00091         /* in eed->f1 we put the valence (amount of faces in edge) */
00092         /* in eed->f2 we put tagged flag as correct loop */
00093         /* in efa->f1 we put tagged flag as correct to select */
00094 
00095         for(eed= em->edges.first; eed; eed= eed->next) {
00096                 eed->f1= 0;
00097                 eed->f2= 0;
00098         }
00099         for(efa= em->faces.first; efa; efa= efa->next) {
00100                 efa->f1= 0;
00101                 if(efa->h==0) {
00102                         efa->e1->f1++;
00103                         efa->e2->f1++;
00104                         efa->e3->f1++;
00105                         if(efa->e4) efa->e4->f1++;
00106                 }
00107         }
00108         
00109         // tag startedge OK
00110         startedge->f2= 1;
00111         
00112         while(looking) {
00113                 looking= 0;
00114                 
00115                 for(efa= em->faces.first; efa; efa= efa->next) {
00116                         if(efa->e4 && efa->f1==0 && efa->h == 0) {      // not done quad
00117                                 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
00118 
00119                                         // if edge tagged, select opposing edge and mark face ok
00120                                         if(efa->e1->f2) {
00121                                                 efa->e3->f2= 1;
00122                                                 efa->f1= 1;
00123                                                 looking= 1;
00124                                         }
00125                                         else if(efa->e2->f2) {
00126                                                 efa->e4->f2= 1;
00127                                                 efa->f1= 1;
00128                                                 looking= 1;
00129                                         }
00130                                         if(efa->e3->f2) {
00131                                                 efa->e1->f2= 1;
00132                                                 efa->f1= 1;
00133                                                 looking= 1;
00134                                         }
00135                                         if(efa->e4->f2) {
00136                                                 efa->e2->f2= 1;
00137                                                 efa->f1= 1;
00138                                                 looking= 1;
00139                                         }
00140                                 }
00141                         }
00142                 }
00143         }
00144         
00145         if(previewlines > 0 && select == 0){
00146 // XXX                  persp(PERSP_VIEW);
00147 // XXX                  glPushMatrix();
00148 // XXX                  mymultmatrix(obedit->obmat);
00149 
00150                         for(efa= em->faces.first; efa; efa= efa->next) {
00151                                 if(efa->v4 == NULL) {  continue; }
00152                                 if(efa->h == 0){
00153                                         if(efa->e1->f2 == 1){
00154                                                 if(efa->e1->h == 1 || efa->e3->h == 1 )
00155                                                         continue;
00156                                                 
00157                                                 v[0][0] = efa->v1;
00158                                                 v[0][1] = efa->v2;
00159                                                 v[1][0] = efa->v4;
00160                                                 v[1][1] = efa->v3;
00161                                         } else if(efa->e2->f2 == 1){
00162                                                 if(efa->e2->h == 1 || efa->e4->h == 1)
00163                                                         continue;
00164                                                 v[0][0] = efa->v2;
00165                                                 v[0][1] = efa->v3;
00166                                                 v[1][0] = efa->v1;
00167                                                 v[1][1] = efa->v4;                                      
00168                                         } else { continue; }
00169                                                                                   
00170                                         for(i=1;i<=previewlines;i++){
00171                                                 co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
00172                                                 co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
00173                                                 co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
00174 
00175                                                 co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
00176                                                 co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
00177                                                 co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];                                        
00178                                                 glColor3ub(255, 0, 255);
00179                                                 glBegin(GL_LINES);      
00180                                                 glVertex3f(co[0][0],co[0][1],co[0][2]);
00181                                                 glVertex3f(co[1][0],co[1][1],co[1][2]);
00182                                                 glEnd();
00183                                         }
00184                                 }
00185                         }
00186                         glPopMatrix();   
00187         } else {        
00188         
00189         /* (de)select the edges */
00190                 for(eed= em->edges.first; eed; eed= eed->next) {
00191                 if(eed->f2) EM_select_edge(eed, select);
00192                 }
00193         }
00194 }
00195 
00196 static void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
00197 {
00198         ViewContext vc; // XXX
00199         EditEdge *nearest=NULL, *eed;
00200         float fac;
00201         int keys = 0, holdnum=0, selectmode, dist;
00202         int mvalo[2] = {0, 0}, mval[2] = {0, 0};
00203         short event=0, val, choosing=1, cancel=0, cuthalf = 0, smooth=0;
00204         short hasHidden = 0;
00205         char msg[128];
00206         
00207         selectmode = em->selectmode;
00208                 
00209         if(em->selectmode & SCE_SELECT_FACE){
00210                 em->selectmode =  SCE_SELECT_EDGE;
00211                 EM_selectmode_set(em);    
00212         }
00213         
00214         
00215         BIF_undo_push("Loopcut Begin");
00216         while(choosing && !cancel){
00217 // XXX          getmouseco_areawin(mval);
00218                 if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) {
00219                         mvalo[0] = mval[0];
00220                         mvalo[1] = mval[1];
00221                         dist= 50;
00222                         nearest = findnearestedge(&vc, &dist);  // returns actual distance in dist
00223 //                      scrarea_do_windraw(curarea);    // after findnearestedge, backbuf!
00224 
00225                         BLI_snprintf(msg, sizeof(msg),"Number of Cuts: %d (S)mooth: %s", numcuts, smooth ? "on":"off");
00226                         
00227 //                      headerprint(msg);
00228                         /* Need to figure preview */
00229                         if(nearest){
00230                                 edgering_sel(em, nearest, 0, numcuts);
00231                          }   
00232 // XXX                  screen_swapbuffers();
00233                         
00234                 /* backbuffer refresh for non-apples (no aux) */
00235 #ifndef __APPLE__
00236 // XXX                  if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
00237 //                              backdrawview3d(0);
00238 //                      }
00239 #endif
00240                 }
00241                 else PIL_sleep_ms(10);  // idle
00242                 
00243                 
00244                 while(qtest()) 
00245                 {
00246                         val=0;
00247 // XXX                  event= extern_qread(&val);
00248                         if(val && (event ==  MOUSEX || event == MOUSEY)){ ; } 
00249                         else if(val && ((event==LEFTMOUSE || event==RETKEY) || (event == MIDDLEMOUSE || event==PADENTER)))
00250                         {
00251                                 if(event == MIDDLEMOUSE){
00252                                         cuthalf = 1;
00253                                 }
00254                                 if (nearest==NULL)
00255                                         cancel = 1;
00256                                 choosing=0;
00257                                 mvalo[0] = -1;
00258                         }
00259                         else if(val && (event==ESCKEY || event==RIGHTMOUSE ))
00260                         {
00261                                 choosing=0;
00262                                 cancel = 1;
00263                                 mvalo[0] = -1;
00264                         }
00265                         else if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE))
00266                         {
00267                                 numcuts++;
00268                                 mvalo[0] = -1;
00269                         }
00270                         else if(val && (event==PADMINUS || event==WHEELDOWNMOUSE))
00271                         {
00272                                 if(numcuts > 1){
00273                                         numcuts--;
00274                                         mvalo[0] = -1;
00275                                 } 
00276                         }
00277                         else if(val && event==SKEY)
00278                         {
00279                                 if(smooth){smooth=0;} 
00280                                 else { smooth=1; }
00281                                 mvalo[0] = -1;
00282                         }
00283                         
00284                         else if(val){
00285                                 holdnum = -1;
00286                                 switch(event){
00287                                         case PAD9:
00288                                         case NINEKEY:
00289                                                 holdnum = 9; break;
00290                                         case PAD8:
00291                                         case EIGHTKEY:
00292                                                 holdnum = 8;break;
00293                                         case PAD7:
00294                                         case SEVENKEY:
00295                                                 holdnum = 7;break;
00296                                         case PAD6:
00297                                         case SIXKEY:
00298                                                 holdnum = 6;break;
00299                                         case PAD5:
00300                                         case FIVEKEY:
00301                                                 holdnum = 5;break;
00302                                         case PAD4:
00303                                         case FOURKEY:
00304                                                 holdnum = 4;break;
00305                                         case PAD3:
00306                                         case THREEKEY:
00307                                                 holdnum = 3; break;
00308                                         case PAD2:
00309                                         case TWOKEY:
00310                                                 holdnum = 2;break;
00311                                         case PAD1:
00312                                         case ONEKEY:
00313                                                 holdnum = 1; break;
00314                                         case PAD0:
00315                                         case ZEROKEY:
00316                                                 holdnum = 0;break;      
00317                                         case BACKSPACEKEY:
00318                                                 holdnum = -2;break;                     
00319                                 }
00320                                 if(holdnum >= 0 && numcuts*10 < 130){
00321                                         if(keys == 0){  // first level numeric entry
00322                                                         if(holdnum > 0){
00323                                                                         numcuts = holdnum;
00324                                                                         keys++;         
00325                                                         }
00326                                         } else if(keys > 0){//highrt level numeric entry
00327                                                         numcuts *= 10;
00328                                                         numcuts += holdnum;
00329                                                         keys++;         
00330                                         }
00331                                 } else if (holdnum == -2){// backspace
00332                                         if (keys > 1){
00333                                                 numcuts /= 10;          
00334                                                 keys--;
00335                                         } else {
00336                                                 numcuts=1;
00337                                                 keys = 0;
00338                                         }
00339                                 }
00340                                 mvalo[0] = -1;
00341                                 break;
00342                         }  // End Numeric Entry                                         
00343                 }  //End while(qtest())
00344         }   // End Choosing
00345 
00346         if(cancel){
00347                 return;   
00348         }
00349         /* clean selection */
00350         for(eed=em->edges.first; eed; eed = eed->next){
00351                 EM_select_edge(eed,0);
00352         }
00353         /* select edge ring */
00354         edgering_sel(em, nearest, 1, 0);
00355         
00356         /* now cut the loops */
00357         if(smooth){
00358                 fac= 1.0f;
00359 // XXX          if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return;
00360                 fac= 0.292f*fac;                        
00361                 esubdivideflag(obedit, em, SELECT,fac,0,B_SMOOTH,numcuts, SUBDIV_CORNER_PATH, SUBDIV_SELECT_LOOPCUT);
00362         } else {
00363                 esubdivideflag(obedit, em, SELECT,0,0,0,numcuts,SUBDIV_CORNER_PATH, SUBDIV_SELECT_LOOPCUT);
00364         }
00365         /* if this was a single cut, enter edgeslide mode */
00366         if(numcuts == 1 && hasHidden == 0){
00367                 if(cuthalf)
00368                         EdgeSlide(em, op, 1,0.0);
00369                 else {
00370                         if(EdgeSlide(em, op, 0,0.0) == -1){
00371                                 BIF_undo();
00372                         }
00373                 }
00374         }
00375         
00376         if(em->selectmode !=  selectmode){
00377                 em->selectmode = selectmode;
00378                 EM_selectmode_set(em);
00379         }       
00380         
00381 //      DAG_id_tag_update(obedit->data, 0);
00382         return;
00383 }
00384 #endif
00385 
00386 /* *************** LOOP SELECT ************* */
00387 #if 0
00388 static short edgeFaces(EditMesh *em, EditEdge *e)
00389 {
00390         EditFace *search=NULL;
00391         short count = 0;
00392         
00393         search = em->faces.first;
00394         while(search){
00395                 if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) 
00396                         count++;
00397                 search = search->next;
00398         }
00399         return count;   
00400 }
00401 #endif
00402 
00403 
00404 
00405 /*   ***************** TRAIL ************************
00406 
00407 Read a trail of mouse coords and return them as an array of CutCurve structs
00408 len returns number of mouse coords read before commiting with RETKEY   
00409 It is up to the caller to free the block when done with it,
00410 
00411 XXX Is only used here, so local inside this file (ton)
00412  */
00413 
00414 #define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
00415 #define TRAIL_FREEHAND 2
00416 #define TRAIL_MIXED    3 /* (1|2) */
00417 #define TRAIL_AUTO     4 
00418 #define TRAIL_MIDPOINTS 8
00419 
00420 typedef struct CutCurve {
00421         float  x; 
00422         float  y;
00423 } CutCurve;
00424 
00425 
00426 /* ******************************************************************** */
00427 /* Knife Subdivide Tool.  Subdivides edges intersected by a mouse trail
00428         drawn by user.
00429         
00430         Currently mapped to KKey when in MeshEdit mode.
00431         Usage:
00432                 Hit Shift K, Select Centers or Exact
00433                 Hold LMB down to draw path, hit RETKEY.
00434                 ESC cancels as expected.
00435    
00436         Contributed by Robert Wenzlaff (Det. Thorn).
00437 
00438         2.5 revamp:
00439         - non modal (no menu before cutting)
00440         - exit on mouse release
00441         - polygon/segment drawing can become handled by WM cb later
00442 
00443 */
00444 
00445 #define KNIFE_EXACT             1
00446 #define KNIFE_MIDPOINT  2
00447 #define KNIFE_MULTICUT  3
00448 
00449 static EnumPropertyItem knife_items[]= {
00450         {KNIFE_EXACT, "EXACT", 0, "Exact", ""},
00451         {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""},
00452         {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""},
00453         {0, NULL, 0, NULL, NULL}
00454 };
00455 
00456 /* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */
00457 
00458 static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct GHash *gh)
00459 {
00460 #define MAXSLOPE 100000
00461         float  x11, y11, x12=0, y12=0, x2max, x2min, y2max;
00462         float  y2min, dist, lastdist=0, xdiff2, xdiff1;
00463         float  m1, b1, m2, b2, x21, x22, y21, y22, xi;
00464         float  yi, x1min, x1max, y1max, y1min, perc=0; 
00465         float  *scr;
00466         float  threshold;
00467         int  i;
00468         
00469         threshold = 0.000001; /*tolerance for vertex intersection*/
00470         // XXX  threshold = scene->toolsettings->select_thresh / 100;
00471         
00472         /* Get screen coords of verts */
00473         scr = BLI_ghash_lookup(gh, e->v1);
00474         x21=scr[0];
00475         y21=scr[1];
00476         
00477         scr = BLI_ghash_lookup(gh, e->v2);
00478         x22=scr[0];
00479         y22=scr[1];
00480         
00481         xdiff2=(x22-x21);  
00482         if (xdiff2) {
00483                 m2=(y22-y21)/xdiff2;
00484                 b2= ((x22*y21)-(x21*y22))/xdiff2;
00485         }
00486         else {
00487                 m2=MAXSLOPE;  /* Verticle slope  */
00488                 b2=x22;      
00489         }
00490         
00491         /*check for *exact* vertex intersection first*/
00492         if(mode!=KNIFE_MULTICUT){
00493                 for (i=0; i<len; i++){
00494                         if (i>0){
00495                                 x11=x12;
00496                                 y11=y12;
00497                         }
00498                         else {
00499                                 x11=c[i].x;
00500                                 y11=c[i].y;
00501                         }
00502                         x12=c[i].x;
00503                         y12=c[i].y;
00504                         
00505                         /*test e->v1*/
00506                         if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){
00507                                 e->v1->f1 = 1;
00508                                 perc = 0;
00509                                 return(perc);
00510                         }
00511                         /*test e->v2*/
00512                         else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){
00513                                 e->v2->f1 = 1;
00514                                 perc = 0;
00515                                 return(perc);
00516                         }
00517                 }
00518         }
00519         
00520         /*now check for edge interesect (may produce vertex intersection as well)*/
00521         for (i=0; i<len; i++){
00522                 if (i>0){
00523                         x11=x12;
00524                         y11=y12;
00525                 }
00526                 else {
00527                         x11=c[i].x;
00528                         y11=c[i].y;
00529                 }
00530                 x12=c[i].x;
00531                 y12=c[i].y;
00532                 
00533                 /* Perp. Distance from point to line */
00534                 if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */
00535                         /* change in sign.  Skip extra math */  
00536                 else dist=x22-x12;      
00537                 
00538                 if (i==0) lastdist=dist;
00539                 
00540                 /* if dist changes sign, and intersect point in edge's Bound Box*/
00541                 if ((lastdist*dist)<=0){
00542                         xdiff1=(x12-x11); /* Equation of line between last 2 points */
00543                         if (xdiff1){
00544                                 m1=(y12-y11)/xdiff1;
00545                                 b1= ((x12*y11)-(x11*y12))/xdiff1;
00546                         }
00547                         else{
00548                                 m1=MAXSLOPE;
00549                                 b1=x12;
00550                         }
00551                         x2max=MAX2(x21,x22)+0.001; /* prevent missed edges   */
00552                         x2min=MIN2(x21,x22)-0.001; /* due to round off error */
00553                         y2max=MAX2(y21,y22)+0.001;
00554                         y2min=MIN2(y21,y22)-0.001;
00555                         
00556                         /* Found an intersect,  calc intersect point */
00557                         if (m1==m2){ /* co-incident lines */
00558                                 /* cut at 50% of overlap area*/
00559                                 x1max=MAX2(x11, x12);
00560                                 x1min=MIN2(x11, x12);
00561                                 xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0;  
00562                                 
00563                                 y1max=MAX2(y11, y12);
00564                                 y1min=MIN2(y11, y12);
00565                                 yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0;
00566                         }                       
00567                         else if (m2==MAXSLOPE){ 
00568                                 xi=x22;
00569                                 yi=m1*x22+b1;
00570                         }
00571                         else if (m1==MAXSLOPE){ 
00572                                 xi=x12;
00573                                 yi=m2*x12+b2;
00574                         }
00575                         else {
00576                                 xi=(b1-b2)/(m2-m1);
00577                                 yi=(b1*m2-m1*b2)/(m2-m1);
00578                         }
00579                         
00580                         /* Intersect inside bounding box of edge?*/
00581                         if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){
00582                                 /*test for vertex intersect that may be 'close enough'*/
00583                                 if(mode!=KNIFE_MULTICUT){
00584                                         if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){
00585                                                 if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){
00586                                                         e->v1->f1 = 1;
00587                                                         perc = 0;
00588                                                         break;
00589                                                 }
00590                                         }
00591                                         if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){
00592                                                 if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){
00593                                                         e->v2->f1 = 1;
00594                                                         perc = 0;
00595                                                         break;
00596                                                 }
00597                                         }
00598                                 }
00599                                 if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21);   
00600                                 else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/
00601                                 //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
00602                                 
00603                                 break;
00604                         }
00605                 }       
00606                 lastdist=dist;
00607         }
00608         return(perc);
00609 } 
00610 
00611 /* for multicut */
00612 #define MAX_CUTS 256
00613 
00614 /* for amount of edges */
00615 #define MAX_CUT_EDGES 1024
00616 
00617 static int knife_cut_exec(bContext *C, wmOperator *op)
00618 {
00619         Object *obedit= CTX_data_edit_object(C);
00620         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
00621         ARegion *ar= CTX_wm_region(C);
00622         EditEdge *eed;
00623         EditVert *eve;
00624         CutCurve curve[MAX_CUT_EDGES];
00625         struct GHash *gh;
00626         float isect=0.0;
00627         float  *scr, co[4];
00628         int len=0;
00629         short numcuts= RNA_int_get(op->ptr, "num_cuts"); 
00630         short mode= RNA_enum_get(op->ptr, "type");
00631 //      int corner_cut_pattern= RNA_enum_get(op->ptr,"corner_cut_pattern");
00632         
00633         /* edit-object needed for matrix, and ar->regiondata for projections to work */
00634         if (ELEM3(NULL, obedit, ar, ar->regiondata))
00635                 return OPERATOR_CANCELLED;
00636         
00637         if (EM_nvertices_selected(em) < 2) {
00638                 error("No edges are selected to operate on");
00639                 BKE_mesh_end_editmesh(obedit->data, em);
00640                 return OPERATOR_CANCELLED;
00641         }
00642 
00643         /* get the cut curve */
00644         RNA_BEGIN(op->ptr, itemptr, "path") {
00645                 
00646                 RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]);
00647                 len++;
00648                 if(len>= MAX_CUT_EDGES) break;
00649         }
00650         RNA_END;
00651         
00652         if(len<2) {
00653                 BKE_mesh_end_editmesh(obedit->data, em);
00654                 return OPERATOR_CANCELLED;
00655         }
00656 
00657         /*store percentage of edge cut for KNIFE_EXACT here.*/
00658         for(eed=em->edges.first; eed; eed= eed->next) 
00659                 eed->tmp.fp = 0.0; 
00660         
00661         /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/
00662         gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife_cut_exec gh");
00663         for(eve=em->verts.first; eve; eve=eve->next){
00664                 scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates");
00665                 VECCOPY(co, eve->co);
00666                 co[3]= 1.0;
00667                 mul_m4_v4(obedit->obmat, co);
00668                 project_float(ar, co, scr);
00669                 BLI_ghash_insert(gh, eve, scr);
00670                 eve->f1 = 0; /*store vertex intersection flag here*/
00671         
00672         }
00673         
00674         eed= em->edges.first;           
00675         while(eed) {    
00676                 if( eed->v1->f & eed->v2->f & SELECT ){         // NOTE: uses vertex select, subdiv doesnt do edges yet
00677                         isect= seg_intersect(eed, curve, len, mode, gh);
00678                         if (isect!=0.0f) eed->f2= 1;
00679                         else eed->f2=0;
00680                         eed->tmp.fp= isect;
00681                 }
00682                 else {
00683                         eed->f2=0;
00684                         eed->f1=0;
00685                 }
00686                 eed= eed->next;
00687         }
00688         
00689         if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, 1, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER);
00690         else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, numcuts, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER);
00691         else esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER);
00692 
00693         eed=em->edges.first;
00694         while(eed){
00695                 eed->f2=0;
00696                 eed->f1=0;
00697                 eed=eed->next;
00698         }       
00699         
00700         BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
00701         
00702         BKE_mesh_end_editmesh(obedit->data, em);
00703 
00704         DAG_id_tag_update(obedit->data, 0);
00705         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
00706 
00707         return OPERATOR_FINISHED;
00708 }
00709 
00710 
00711 void MESH_OT_knife_cut(wmOperatorType *ot)
00712 {
00713         PropertyRNA *prop;
00714         
00715         ot->name= "Knife Cut";
00716         ot->description= "Cut selected edges and faces into parts";
00717         ot->idname= "MESH_OT_knife_cut";
00718         
00719         ot->invoke= WM_gesture_lines_invoke;
00720         ot->modal= WM_gesture_lines_modal;
00721         ot->exec= knife_cut_exec;
00722         ot->cancel= WM_gesture_lines_cancel;
00723         
00724         ot->poll= EM_view3d_poll;
00725         
00726         /* flags */
00727         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00728         
00729         RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", "");
00730         prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
00731         RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
00732         RNA_def_int(ot->srna, "num_cuts", 1, 1, MAX_CUTS, "Number of Cuts", "Only for Multi-Cut", 1, MAX_CUTS);
00733         // 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");
00734         
00735         /* internal */
00736         RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
00737 }
00738 
00739 /* ******************************************************* */
00740