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