~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to source/blender/src/editmesh_loop.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2005-11-06 12:40:03 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051106124003-3pgs7tcg5rox96xg
Tags: 2.37a-1.1
* Non-maintainer upload.
* Split out parts of 01_SConstruct_debian.dpatch again: root_build_dir
  really needs to get adjusted before the clean target runs - closes: #333958,
  see #288882 for reference

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * $Id: 
 
3
 *
 
4
 * ***** BEGIN GPL/BL DUAL 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. The Blender
 
10
 * Foundation also sells licenses for use in proprietary software under
 
11
 * the Blender License.  See http://www.blender.org/BL/ for information
 
12
 * about this.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program; if not, write to the Free Software Foundation,
 
21
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
22
 *
 
23
 * The Original Code is Copyright (C) 2004 by NaN Holding BV.
 
24
 * All rights reserved.
 
25
 *
 
26
 * The Original Code is: all of this file.
 
27
 *
 
28
 * Contributor(s): none yet.
 
29
 *
 
30
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 
31
 */
 
32
 
 
33
/*
 
34
 
 
35
editmesh_loop: tools with own drawing subloops, select, knife, subdiv
 
36
 
 
37
*/
 
38
 
 
39
#include <stdlib.h>
 
40
#include <string.h>
 
41
#include <math.h>
 
42
 
 
43
#include "MEM_guardedalloc.h"
 
44
 
 
45
 
 
46
#include "DNA_mesh_types.h"
 
47
#include "DNA_meshdata_types.h"
 
48
#include "DNA_object_types.h"
 
49
#include "DNA_scene_types.h"
 
50
#include "DNA_screen_types.h"
 
51
#include "DNA_view3d_types.h"
 
52
 
 
53
#include "BLI_blenlib.h"
 
54
#include "BLI_arithb.h"
 
55
#include "BLI_editVert.h"
 
56
 
 
57
#include "BKE_displist.h"
 
58
#include "BKE_global.h"
 
59
#include "BKE_library.h"
 
60
#include "BKE_mesh.h"
 
61
#include "BKE_object.h"
 
62
#include "BKE_utildefines.h"
 
63
 
 
64
#include "BIF_cursors.h"
 
65
#include "BIF_editmesh.h"
 
66
#include "BIF_gl.h"
 
67
#include "BIF_glutil.h"
 
68
#include "BIF_graphics.h"
 
69
#include "BIF_interface.h"
 
70
#include "BIF_mywindow.h"
 
71
#include "BIF_screen.h"
 
72
#include "BIF_space.h"
 
73
#include "BIF_toolbox.h"
 
74
 
 
75
#include "BSE_view.h"
 
76
#include "BSE_edit.h"
 
77
#include "BSE_drawview.h"
 
78
 
 
79
#include "BDR_drawobject.h"
 
80
#include "BDR_editobject.h"
 
81
#include "PIL_time.h"
 
82
 
 
83
#include "mydevice.h"
 
84
#include "blendef.h"
 
85
 
 
86
#include "editmesh.h"
 
87
 
 
88
/* next 2 includes for knife tool... shouldnt be! (ton) */
 
89
#include "GHOST_C-api.h"
 
90
#include "winlay.h"
 
91
 
 
92
 
 
93
/* *************** LOOP SELECT ************* */
 
94
 
 
95
static short edgeFaces(EditEdge *e){
 
96
        EditMesh *em = G.editMesh;
 
97
        EditFace *search=NULL;
 
98
        short count = 0;
 
99
        
 
100
        search = em->faces.first;
 
101
        while(search){
 
102
                if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) 
 
103
                        count++;
 
104
        search = search->next;
 
105
        }
 
106
        return count;   
 
107
}
 
108
 
 
109
/* this utility function checks to see if 2 edit edges share a face,
 
110
        returns 1 if they do
 
111
        returns 0 if they do not, or if the function is passed the same edge 2 times
 
112
*/
 
113
static short sharesFace(EditEdge* e1, EditEdge* e2)
 
114
{
 
115
        EditMesh *em = G.editMesh;
 
116
        EditFace *search=NULL;
 
117
        search = em->faces.first;
 
118
        if (e1 == e2){
 
119
                return 0 ;
 
120
        }
 
121
        while(search){
 
122
                if(
 
123
                        ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) &&
 
124
                        ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2))
 
125
                        ) {
 
126
                        return 1;
 
127
                }
 
128
                search = search->next;
 
129
        }
 
130
        return 0;
 
131
}
 
132
/* This function selects a vertex loop based on a each succesive edge having a valance of 4
 
133
   and not sharing a face with the previous edge */
 
134
 
 
135
/* It uses ->f flags still, which isn't causing bugs now, but better be put in ->f1 (ton) */
 
136
 
 
137
void vertex_loop_select() 
 
138
{
 
139
        EditMesh *em = G.editMesh;
 
140
        EditVert *v1=NULL,*v2=NULL;
 
141
        EditEdge *search=NULL,*startEdge=NULL,*valSearch = NULL,*nearest = NULL,*compEdge;
 
142
        EditEdge *EdgeVal[5] = {NULL,NULL,NULL,NULL,NULL};
 
143
        short numEdges=0,curEdge = 0,looking = 1,edgeValCount = 0,i=0,looped = 0,choosing = 1,event,noloop=0,cancel=0, val;
 
144
        short protect = 0, dist= 50;
 
145
        short mvalo[2] = {0,0}, mval[2];
 
146
 
 
147
        SetBlenderCursor(BC_VLOOPCURSOR);
 
148
        for(search=em->edges.first;search;search=search->next)
 
149
                numEdges++;
 
150
 
 
151
        /* start with v1 and go in one direction. */
 
152
        while(choosing){
 
153
                getmouseco_areawin(mval);
 
154
                if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) {
 
155
 
 
156
                        mvalo[0] = mval[0];
 
157
                        mvalo[1] = mval[1];
 
158
 
 
159
                        dist= 50;
 
160
                        nearest = findnearestedge(&dist);       // returns actual distance in dist
 
161
                        
 
162
                        scrarea_do_windraw(curarea);    // after findnearestedge, backbuf!
 
163
 
 
164
                        if (nearest && edgeFaces(nearest)==2) {
 
165
                                for(search = em->edges.first;search;search=search->next)
 
166
                                        search->f &= ~32;
 
167
                                        
 
168
                                compEdge = startEdge = nearest;
 
169
                                nearest->f |= 32;
 
170
                                curEdge = 0;
 
171
                                v1 = startEdge->v1;
 
172
                                v2 = startEdge->v2;
 
173
                                looking = 1;
 
174
                                while(looking){
 
175
                                        if(protect++ > numEdges) break;
 
176
                                        if(edgeFaces(compEdge) != 2) break;
 
177
                                        /*Find Edges that have v1*/
 
178
                                        edgeValCount = -1;
 
179
                                        EdgeVal[0] = EdgeVal[1] = EdgeVal[2] = NULL;
 
180
                                        
 
181
                                        for(valSearch = em->edges.first;valSearch;valSearch = valSearch->next){
 
182
                                                if(valSearch->v1 == v1 || valSearch->v2 == v1){
 
183
                                                        if(valSearch != compEdge){
 
184
                                                                if((valSearch->v1->h == 0) && (valSearch->v2->h == 0)){
 
185
                                                                        if(edgeFaces(valSearch) == 2){
 
186
                                                                                edgeValCount++;                                                 
 
187
                                                                                EdgeVal[edgeValCount] = valSearch;
 
188
                                                                        }
 
189
                                                                }
 
190
                                                        }
 
191
                                                }
 
192
                                                if(edgeValCount == 3)break;
 
193
                                        }
 
194
                                        /* Check that there was a valance of 4*/
 
195
                                        if(edgeValCount != 2){
 
196
                                                noloop = 1;
 
197
                                                looking = 0;
 
198
                                                break;
 
199
                                        }
 
200
                                        else{
 
201
                                        /* There were 3 edges, so find the one that does not share the previous edge */
 
202
                                                for(i=0;i<3;i++){
 
203
                                                        if(sharesFace(compEdge,EdgeVal[i]) == 0){
 
204
                                                                /* We went all the way around the loop */
 
205
                                                                if(EdgeVal[i] == nearest){
 
206
                                                                        looking = 0;
 
207
                                                                        looped = 1;
 
208
                                                                        break;
 
209
                                                                }
 
210
                                                                else{
 
211
                                                                        /* we are still in the loop, so add the next edge*/
 
212
                                                                        curEdge++;
 
213
                                                                        EdgeVal[i]->f |= 32;
 
214
                                                                        compEdge = EdgeVal[i];
 
215
                                                                        if(compEdge->v1 == v1)
 
216
                                                                                v1 = compEdge->v2;
 
217
                                                                        else
 
218
                                                                                v1 = compEdge->v1;
 
219
                                                                }
 
220
                                                        }
 
221
                                                }
 
222
                                        }
 
223
                                }       
 
224
                                compEdge = nearest;
 
225
                                looking = 1;
 
226
                                protect = 0;
 
227
                                while(looking/* && !looped*/){
 
228
                                        if(protect++ > numEdges) break;
 
229
                                        if(edgeFaces(compEdge) != 2) break;
 
230
                                        /*Find Edges that have v1*/
 
231
                                        edgeValCount = -1;
 
232
                                        EdgeVal[0] = EdgeVal[1] = EdgeVal[2] = NULL;
 
233
                                        
 
234
                                        for(valSearch = em->edges.first;valSearch;valSearch = valSearch->next){
 
235
                                                if(valSearch->v1 == v2 || valSearch->v2 == v2){
 
236
                                                        if(valSearch != compEdge){
 
237
                                                                if((valSearch->v1->h == 0) && (valSearch->v2->h == 0)){
 
238
                                                                        if(edgeFaces(valSearch) == 2){
 
239
                                                                                edgeValCount++;                                                 
 
240
                                                                                EdgeVal[edgeValCount] = valSearch;
 
241
                                                                        }
 
242
                                                                }
 
243
                                                        }
 
244
                                                }
 
245
                                                if(edgeValCount == 3)break;
 
246
                                        }
 
247
                                        /* Check that there was a valance of 4*/
 
248
                                        if(edgeValCount != 2){
 
249
                                                noloop = 1;
 
250
                                                looking = 0;
 
251
                                                break;
 
252
                                        }
 
253
                                        else{
 
254
                                        /* There were 3 edges, so find the one that does not share the previous edge */
 
255
                                                for(i=0;i<3;i++){
 
256
                                                        if(sharesFace(compEdge,EdgeVal[i]) == 0){
 
257
                                                                /* We went all the way around the loop */
 
258
                                                                if(EdgeVal[i] == nearest){
 
259
                                                                        looking = 0;
 
260
                                                                        looped = 1;
 
261
                                                                        break;
 
262
                                                                }
 
263
                                                                else{
 
264
                                                                        /* we are still in the loop, so add the next edge*/
 
265
                                                                        curEdge++;
 
266
                                                                        EdgeVal[i]->f |= 32;
 
267
                                                                        compEdge = EdgeVal[i];
 
268
                                                                        if(compEdge->v1 == v2)
 
269
                                                                                v2 = compEdge->v2;
 
270
                                                                        else
 
271
                                                                                v2 = compEdge->v1;
 
272
                                                                }
 
273
                                                        }
 
274
                                                }
 
275
                                        }
 
276
                                }
 
277
                                /* set up for opengl drawing in the 3d window */
 
278
                                persp(PERSP_VIEW);
 
279
                                glPushMatrix();
 
280
                                mymultmatrix(G.obedit->obmat);
 
281
                                glColor3ub(0, 255, 255);
 
282
                                for(search = em->edges.first;search;search= search->next){
 
283
                                        if(search->f & 32){
 
284
                                                glBegin(GL_LINES);                      
 
285
                                                glVertex3f(search->v1->co[0],search->v1->co[1],search->v1->co[2]);
 
286
                                                glVertex3f(search->v2->co[0],search->v2->co[1],search->v2->co[2]);
 
287
                                                glEnd();
 
288
                                        }
 
289
                                }               
 
290
 
 
291
                                glPopMatrix();
 
292
                        }
 
293
 
 
294
                        screen_swapbuffers();
 
295
 
 
296
                /* backbuffer refresh for non-apples (no aux) */
 
297
#ifndef __APPLE__
 
298
                        if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
 
299
                                backdrawview3d(0);
 
300
                        }
 
301
#endif
 
302
                }
 
303
                else PIL_sleep_ms(10);  // idle
 
304
                
 
305
                while(qtest()) 
 
306
                {
 
307
                        val=0;
 
308
                        event= extern_qread(&val);
 
309
                        if(val && ((event==LEFTMOUSE || event==RETKEY) || event == MIDDLEMOUSE))
 
310
                        {
 
311
                                if (nearest==NULL)
 
312
                                        cancel = 1;
 
313
                                choosing=0;
 
314
                                break;
 
315
                        }
 
316
                        if(val && (event==ESCKEY || event==RIGHTMOUSE ))
 
317
                        {
 
318
                                choosing=0;
 
319
                                cancel = 1;
 
320
                                break;
 
321
                        }
 
322
                        if(val && (event==BKEY && G.qual==LR_ALTKEY ))
 
323
                        {                       
 
324
                                
 
325
                                SetBlenderCursor(SYSCURSOR);
 
326
                                loopoperations(LOOP_SELECT);
 
327
                                return;
 
328
                        }
 
329
                }
 
330
        }
 
331
        if(!cancel){
 
332
                /* If this is a unmodified select, clear the selection */
 
333
                
 
334
                /* XXX note that !1 is 0, so it not only clears bit 1 (ton) */
 
335
                if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){
 
336
                        for(search = em->edges.first;search;search= search->next){
 
337
                                search->v1->f &= !1;
 
338
                                search->v2->f &= !1;
 
339
                        }
 
340
                        EM_clear_flag_all(SELECT);      /* XXX probably that's sufficient */
 
341
                }
 
342
                /* Alt was not pressed, so add to the selection */
 
343
                if(!(G.qual & LR_ALTKEY)){
 
344
                        for(search = em->edges.first;search;search= search->next){
 
345
                                if(search->f & 32){
 
346
                                        search->v1->f |= 1;
 
347
                                        search->v2->f |= 1;
 
348
                                }
 
349
                                search->f &= ~32;
 
350
                        }
 
351
                        /* XXX this will correctly flush */
 
352
                }
 
353
                /* alt was pressed, so subtract from the selection */
 
354
                else
 
355
                {
 
356
                        /* XXX this doesnt flush correct in face select mode */
 
357
                        for(search = em->edges.first;search;search= search->next){
 
358
                                if(search->f & 32){
 
359
                                        search->v1->f &= !1;
 
360
                                        search->v2->f &= !1;
 
361
                                        EM_select_edge(search, 0);      // the call to deselect edge
 
362
                                }
 
363
                                search->f &= ~32;
 
364
                        }
 
365
                }
 
366
                
 
367
                EM_select_flush(); // flushes vertex -> edge -> face selection
 
368
                
 
369
                countall();
 
370
                
 
371
                BIF_undo_push("Select Vertex Loop");
 
372
        }
 
373
 
 
374
        addqueue(curarea->win, REDRAW, 1); 
 
375
        SetBlenderCursor(SYSCURSOR);
 
376
        return;
 
377
}
 
378
 
 
379
/* *********** END LOOP SELECT ********** */
 
380
 
 
381
 
 
382
 
 
383
/*   ***************** TRAIL ************************
 
384
 
 
385
Read a trail of mouse coords and return them as an array of CutCurve structs
 
386
len returns number of mouse coords read before commiting with RETKEY   
 
387
It is up to the caller to free the block when done with it,
 
388
 
 
389
XXX Is only used here, so local inside this file (ton)
 
390
 */
 
391
 
 
392
#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
 
393
#define TRAIL_FREEHAND 2
 
394
#define TRAIL_MIXED    3 /* (1|2) */
 
395
#define TRAIL_AUTO     4 
 
396
#define TRAIL_MIDPOINTS 8
 
397
 
 
398
typedef struct CutCurve {
 
399
        short  x; 
 
400
        short  y;
 
401
} CutCurve;
 
402
 
 
403
static CutCurve *get_mouse_trail(int *len, char mode){
 
404
 
 
405
        CutCurve *curve,*temp;
 
406
        short event, val, ldown=0, restart=0, rubberband=0;
 
407
        short  mval[2], lockaxis=0, lockx=0, locky=0, lastx=0, lasty=0;
 
408
        int i=0, j, blocks=1, lasti=0;
 
409
        
 
410
        *len=0;
 
411
        curve=(CutCurve *)MEM_callocN(1024*sizeof(CutCurve), "MouseTrail");
 
412
 
 
413
        if (!curve) {
 
414
                printf("failed to allocate memory in get_mouse_trail()\n");
 
415
                return(NULL);
 
416
        }
 
417
        mywinset(curarea->win);
 
418
        glDrawBuffer(GL_FRONT);
 
419
        
 
420
        headerprint("LMB to draw, Enter to finish, ESC to abort.");
 
421
 
 
422
        persp(PERSP_WIN);
 
423
        
 
424
        glColor3ub(200, 200, 0);
 
425
        
 
426
        while(TRUE) {
 
427
                
 
428
                event=extern_qread(&val);       /* Enter or RMB indicates finish */
 
429
                if(val) {
 
430
                        if(event==RETKEY || event==PADENTER) break;
 
431
                }
 
432
                
 
433
                if( event==ESCKEY || event==RIGHTMOUSE ) {
 
434
                        if (curve) MEM_freeN(curve);
 
435
                        *len=0;
 
436
                        glFlush();
 
437
                        glDrawBuffer(GL_BACK);
 
438
                        return(NULL);
 
439
                        break;
 
440
                }       
 
441
                
 
442
                if (rubberband)  { /* rubberband mode, undraw last rubberband */
 
443
                        glLineWidth(2.0);
 
444
                        sdrawXORline(curve[i-1].x, curve[i-1].y,mval[0], mval[1]); 
 
445
                        glLineWidth(1.0);
 
446
                        glFlush();
 
447
                        rubberband=0;
 
448
                }
 
449
                
 
450
                getmouseco_areawin(mval);
 
451
                
 
452
                if (lockaxis==1) mval[1]=locky;
 
453
                if (lockaxis==2) mval[0]=lockx;
 
454
                
 
455
                if ( ((i==0) || (mval[0]!=curve[i-1].x) || (mval[1]!=curve[i-1].y))
 
456
                        && (get_mbut() & L_MOUSE) ){ /* record changes only, if LMB down */
 
457
                        
 
458
                        lastx=curve[i].x=mval[0];
 
459
                        lasty=curve[i].y=mval[1];
 
460
                        
 
461
                        lockaxis=0;
 
462
                        
 
463
                        i++; 
 
464
                        
 
465
                        ldown=1;
 
466
                        if (restart) { 
 
467
                                for(j=1;j<i;j++) sdrawXORline(curve[j-1].x, curve[j-1].y, curve[j].x, curve[j].y);
 
468
                                if (rubberband) sdrawXORline(curve[j].x, curve[j].y, mval[0], mval[1]);
 
469
                                glFlush();
 
470
                                rubberband=0;
 
471
                                lasti=i=0;
 
472
                                restart=0;
 
473
                                ldown=0;
 
474
                        }
 
475
                }
 
476
                
 
477
                if ((event==MIDDLEMOUSE)&&(get_mbut()&M_MOUSE)&&(i)){/*MMB Down*/
 
478
                /*determine which axis to lock to, or clear if locked */
 
479
                        if (lockaxis) lockaxis=0;
 
480
                        else if (abs(curve[i-1].x-mval[0]) > abs(curve[i-1].y-mval[1])) lockaxis=1;
 
481
                        else lockaxis=2;
 
482
                        
 
483
                        if (lockaxis) {
 
484
                                lockx=lastx;
 
485
                                locky=lasty;
 
486
                        }
 
487
                }
 
488
                
 
489
                if ((i>1)&&(i!=lasti)) {  /*Draw recorded part of curve */
 
490
                        sdrawline(curve[i-2].x, curve[i-2].y, curve[i-1].x, curve[i-1].y);
 
491
                        glFlush();
 
492
                }
 
493
                
 
494
                if ((i==lasti)&&(i>0)) { /*Draw rubberband */
 
495
                        glLineWidth(2.0);
 
496
                        sdrawXORline(curve[i-1].x, curve[i-1].y,mval[0], mval[1]);
 
497
                        glLineWidth(1.0);
 
498
                        glFlush();
 
499
                        rubberband=1;
 
500
                }
 
501
                lasti=i;
 
502
 
 
503
                if (i>=blocks*1024) { /* reallocate data if out of room */
 
504
                        temp=curve;
 
505
                        curve=(CutCurve *)MEM_callocN((blocks+1)*1024*sizeof(CutCurve), "MouseTrail");
 
506
                        if (!curve) {
 
507
                                printf("failed to re-allocate memory in get_mouse_trail()\n");
 
508
                                return(NULL);
 
509
                        }
 
510
                        memcpy(curve, temp, blocks*1024*sizeof(CutCurve));
 
511
                        blocks++;
 
512
                        MEM_freeN(temp);
 
513
                }
 
514
        }
 
515
 
 
516
        glFlush();
 
517
        glDrawBuffer(GL_BACK);
 
518
        persp(PERSP_VIEW);
 
519
 
 
520
        *len=i;
 
521
 
 
522
        return(curve);
 
523
}
 
524
 
 
525
 
 
526
 
 
527
 
 
528
/* ******************************************************************** */
 
529
/* Knife Subdivide Tool.  Subdivides edges intersected by a mouse trail
 
530
        drawn by user.
 
531
        
 
532
        Currently mapped to KKey when in MeshEdit mode.
 
533
        Usage:
 
534
                Hit Shift K, Select Centers or Exact
 
535
                Hold LMB down to draw path, hit RETKEY.
 
536
                ESC cancels as expected.
 
537
   
 
538
        Contributed by Robert Wenzlaff (Det. Thorn).
 
539
*/
 
540
 
 
541
/* prototype */
 
542
short seg_intersect(struct EditEdge * e, CutCurve *c, int len);
 
543
 
 
544
void KnifeSubdivide(char mode)
 
545
{
 
546
        EditMesh *em = G.editMesh;
 
547
        int oldcursor, len=0;
 
548
        short isect=0;
 
549
        CutCurve *curve;                
 
550
        EditEdge *eed; 
 
551
        Window *win;    
 
552
        
 
553
        if (G.obedit==0) return;
 
554
 
 
555
        if (EM_nvertices_selected() < 2) {
 
556
                error("No edges are selected to operate on");
 
557
                return;
 
558
        }
 
559
 
 
560
        if (mode==KNIFE_PROMPT) {
 
561
                short val= pupmenu("Cut Type %t|Exact Line%x1|Midpoints%x2");
 
562
                if(val<1) return;
 
563
                mode= val;      // warning, mode is char, pupmenu returns -1 with ESC
 
564
        }
 
565
 
 
566
        calc_meshverts_ext();  /*Update screen coords for current window */
 
567
        
 
568
        /* Set a knife cursor here */
 
569
        oldcursor=get_cursor();
 
570
 
 
571
        win=winlay_get_active_window();
 
572
        
 
573
        SetBlenderCursor(BC_KNIFECURSOR);
 
574
        
 
575
        curve=get_mouse_trail(&len, TRAIL_MIXED);
 
576
        
 
577
        if (curve && len && mode){
 
578
                eed= em->edges.first;           
 
579
                while(eed) {    
 
580
                        if( eed->f & SELECT ){
 
581
                                isect=seg_intersect(eed, curve, len);
 
582
                                if (isect) eed->f2= 1;
 
583
                                else eed->f2=0;
 
584
                                eed->f1= isect;
 
585
                                //printf("isect=%i\n", isect);
 
586
                        }
 
587
                        else {
 
588
                                eed->f2=0;
 
589
                                eed->f1=0;
 
590
                        }
 
591
                        eed= eed->next;
 
592
                }
 
593
                
 
594
                if (mode==1) subdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD);
 
595
                else if (mode==2) subdivideflag(1, 0, B_KNIFE);
 
596
                
 
597
                eed=em->edges.first;
 
598
                while(eed){
 
599
                        eed->f2=0;
 
600
                        eed->f1=0;
 
601
                        eed=eed->next;
 
602
                }       
 
603
        }
 
604
        /* Return to old cursor and flags...*/
 
605
        
 
606
        addqueue(curarea->win,  REDRAW, 0);
 
607
        window_set_cursor(win, oldcursor);
 
608
        if (curve) MEM_freeN(curve);
 
609
 
 
610
        BIF_undo_push("Knife");
 
611
}
 
612
 
 
613
/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */
 
614
 
 
615
short seg_intersect(EditEdge *e, CutCurve *c, int len){
 
616
#define MAXSLOPE 100000
 
617
        short isect=0;
 
618
        float  x11, y11, x12=0, y12=0, x2max, x2min, y2max;
 
619
        float  y2min, dist, lastdist=0, xdiff2, xdiff1;
 
620
        float  m1, b1, m2, b2, x21, x22, y21, y22, xi;
 
621
        float  yi, x1min, x1max, y1max, y1min, perc=0; 
 
622
        float  scr[2], co[4];
 
623
        int  i;
 
624
        
 
625
        /* Get screen coords of verts (v->xs and v->ys clip if off screen */
 
626
        VECCOPY(co, e->v1->co);
 
627
        co[3]= 1.0;
 
628
        Mat4MulVec4fl(G.obedit->obmat, co);
 
629
        project_float(co, scr);
 
630
        x21=scr[0];
 
631
        y21=scr[1];
 
632
        
 
633
        VECCOPY(co, e->v2->co);
 
634
        co[3]= 1.0;
 
635
        Mat4MulVec4fl(G.obedit->obmat, co);
 
636
        project_float(co, scr);
 
637
        x22=scr[0];
 
638
        y22=scr[1];
 
639
        
 
640
        xdiff2=(x22-x21);  
 
641
        if (xdiff2) {
 
642
                m2=(y22-y21)/xdiff2;
 
643
                b2= ((x22*y21)-(x21*y22))/xdiff2;
 
644
        }
 
645
        else {
 
646
                m2=MAXSLOPE;  /* Verticle slope  */
 
647
                b2=x22;      
 
648
        }
 
649
        for (i=0; i<len; i++){
 
650
                if (i>0){
 
651
                        x11=x12;
 
652
                        y11=y12;
 
653
                }
 
654
                else {
 
655
                        x11=c[i].x;
 
656
                        y11=c[i].y;
 
657
                }
 
658
                x12=c[i].x;
 
659
                y12=c[i].y;
 
660
 
 
661
                /* Perp. Distance from point to line */
 
662
                if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */
 
663
                                                       /* change in sign.  Skip extra math */   
 
664
                else dist=x22-x12;      
 
665
                
 
666
                if (i==0) lastdist=dist;
 
667
                
 
668
                /* if dist changes sign, and intersect point in edge's Bound Box*/
 
669
                if ((lastdist*dist)<=0){
 
670
                        xdiff1=(x12-x11); /* Equation of line between last 2 points */
 
671
                        if (xdiff1){
 
672
                                m1=(y12-y11)/xdiff1;
 
673
                                b1= ((x12*y11)-(x11*y12))/xdiff1;
 
674
                        }
 
675
                        else{
 
676
                                m1=MAXSLOPE;
 
677
                                b1=x12;
 
678
                        }
 
679
                        x2max=MAX2(x21,x22)+0.001; /* prevent missed edges   */
 
680
                        x2min=MIN2(x21,x22)-0.001; /* due to round off error */
 
681
                        y2max=MAX2(y21,y22)+0.001;
 
682
                        y2min=MIN2(y21,y22)-0.001;
 
683
                        
 
684
                        /* Found an intersect,  calc intersect point */
 
685
                        if (m1==m2){            /* co-incident lines */
 
686
                                                /* cut at 50% of overlap area*/
 
687
                                x1max=MAX2(x11, x12);
 
688
                                x1min=MIN2(x11, x12);
 
689
                                xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0;  
 
690
                                
 
691
                                y1max=MAX2(y11, y12);
 
692
                                y1min=MIN2(y11, y12);
 
693
                                yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0;
 
694
                        }                       
 
695
                        else if (m2==MAXSLOPE){ 
 
696
                                xi=x22;
 
697
                                yi=m1*x22+b1;
 
698
                        }
 
699
                        else if (m1==MAXSLOPE){ 
 
700
                                xi=x12;
 
701
                                yi=m2*x12+b2;
 
702
                        }
 
703
                        else {
 
704
                                xi=(b1-b2)/(m2-m1);
 
705
                                yi=(b1*m2-m1*b2)/(m2-m1);
 
706
                        }
 
707
                        
 
708
                        /* Intersect inside bounding box of edge?*/
 
709
                        if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){
 
710
                                if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21);   
 
711
                                else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/
 
712
                                isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
 
713
                                break;
 
714
                        }
 
715
                }       
 
716
                lastdist=dist;
 
717
        }
 
718
        return(isect);
 
719
 
720
 
 
721
/* ******************** LOOP ******************************************* */
 
722
 
 
723
/* XXX: this loop function is totally out of control!
 
724
   can be half the code, and using structured functions (ton) */
 
725
   
 
726
/* 
 
727
functionality: various loop functions
 
728
parameters: mode tells the function what it should do with the loop:
 
729
                LOOP_SELECT = select
 
730
                LOOP_CUT = cut in half
 
731
*/      
 
732
 
 
733
void loopoperations(char mode)
 
734
{
 
735
        EditMesh *em = G.editMesh;
 
736
        EditVert* look = NULL;
 
737
        EditEdge *start, *eed, *opposite,*currente, *oldstart;
 
738
        EditEdge **tagged = NULL,**taggedsrch = NULL,*close;
 
739
        EditFace *efa,**percentfacesloop = NULL, *currentvl,  *formervl;        
 
740
        short lastface=0, foundedge=0, c=0, tri=0, side=1, totface=0, searching=1, event=0, noface=1;
 
741
        short skip,nextpos,percentfaces, dist=50;
 
742
 
 
743
        int i=0,ect=0,j=0,k=0,cut,smooth,timesthrough=0,inset = 0;
 
744
 
 
745
        float percentcut, outcut;
 
746
 
 
747
        char mesg[100];
 
748
 
 
749
        if ((G.obedit==0) || (em->faces.first==0)) return;
 
750
        
 
751
        SetBlenderCursor(BC_VLOOPCURSOR);
 
752
        
 
753
        /* Clear flags */
 
754
        for(eed=em->edges.first; eed; eed=eed->next) eed->f2= 0;
 
755
        for(efa= em->faces.first; efa; efa=efa->next) efa->f1= 0;
 
756
        
 
757
        start=NULL;
 
758
        oldstart=NULL;
 
759
 
 
760
        while(searching){
 
761
                
 
762
                /* reset variables */
 
763
                start=eed=opposite=currente=0;
 
764
                efa=currentvl=formervl=0;
 
765
                side=noface=1;
 
766
                lastface=foundedge=c=tri=totface=0;             
 
767
                                
 
768
                //start=findnearestvisibleedge();
 
769
                dist= 50;
 
770
                start= findnearestedge(&dist);
 
771
                
 
772
                /* used flags in the code:
 
773
                   vertex->f & 2: in findnearestvisibleedge
 
774
                   edge->f2 : subdiv codes
 
775
                   efa->f1 : subdiv codes
 
776
                */
 
777
                
 
778
                /* If the edge doesn't belong to a face, it's not a valid starting edge */
 
779
                /* and only accept starting edge if it is part of at least one visible face */
 
780
                if(start){
 
781
                        start->f2 |= 16;
 
782
                        efa=em->faces.first;
 
783
                        while(efa){
 
784
                                /* since this edge is on the face, check if the face is hidden */
 
785
                                if( efa->h==0  ){
 
786
                                        if(efa->e1->f2 & 16){
 
787
                                                noface=0;
 
788
                                                efa->e1->f2 &= ~16;
 
789
                                        }
 
790
                                        else if(efa->e2->f2 & 16){                                      
 
791
                                                noface=0;
 
792
                                                efa->e2->f2 &= ~16;
 
793
                                        }
 
794
                                        else if(efa->e3->f2 & 16){                                      
 
795
                                                noface=0;
 
796
                                                efa->e3->f2 &= ~16;
 
797
                                        }
 
798
                                        else if(efa->e4 && (efa->e4->f2 & 16)){                                 
 
799
                                                noface=0;
 
800
                                                efa->e4->f2 &= ~16;
 
801
                                        }
 
802
                                }
 
803
                                efa=efa->next;
 
804
                        }                       
 
805
                }
 
806
                                
 
807
                /* Did we find anything that is selectable? */
 
808
                if(start && !noface && (oldstart==NULL || start!=oldstart)){
 
809
                                        
 
810
                        /* If we stay in the neighbourhood of this edge, we don't have to recalculate the loop everytime*/
 
811
                        oldstart=start; 
 
812
                        
 
813
                        /* Clear flags */
 
814
                        for(eed=em->edges.first; eed; eed=eed->next){                   
 
815
                                eed->f2 &= ~(2|4|8|32|64);
 
816
                                eed->v1->f &= ~(2|8|16); // xxxx
 
817
                                eed->v2->f &= ~(2|8|16);                                
 
818
                        }
 
819
                        
 
820
                        for(efa= em->faces.first; efa; efa=efa->next){                  
 
821
                                efa->f1 &= ~(4|8);
 
822
                                totface++;                              
 
823
                        }
 
824
                                        
 
825
                        /* Tag the starting edge */
 
826
                        start->f2 |= (2|4|8|64);                                
 
827
                        start->v1->f |= 2;  /* xxxx */
 
828
                        start->v2->f |= 2;              
 
829
                        
 
830
                        currente=start;                                         
 
831
                        
 
832
                        /*-----Limit the Search----- */
 
833
                        while(!lastface && c<totface+1){
 
834
                                
 
835
                                /*----------Get Loop------------------------*/
 
836
                                tri=foundedge=lastface=0;                                                                                                       
 
837
                                efa= em->faces.first;           
 
838
                                while(efa && !foundedge && !tri){
 
839
                                                                        
 
840
                                        if(!(efa->v4)){ /* Exception for triangular faces */
 
841
                                                
 
842
                                                if((efa->e1->f2 | efa->e2->f2 | efa->e3->f2) & 2){
 
843
                                                        if(!(efa->f1 & 4)){                                                             
 
844
                                                                tri=1;
 
845
                                                                currentvl=efa;
 
846
                                                                if(side==1) efa->f1 |= 4;
 
847
                                                        }
 
848
                                                }                                               
 
849
                                        }
 
850
                                        else{
 
851
                                                
 
852
                                                if((efa->e1->f2 | efa->e2->f2 | efa->e3->f2 | efa->e4->f2) & 2){
 
853
                                                        
 
854
                                                        if(c==0){       /* just pick a face, doesn't matter wich side of the edge we go to */
 
855
                                                                if(!(efa->f1 & 4)){
 
856
                                                                        
 
857
                                                                        if(!(efa->e1->v1->f & 2) && !(efa->e1->v2->f & 2)){ // xxxxx
 
858
                                                                                if(efa->e1->h==0){
 
859
                                                                                        opposite=efa->e1;                                                                                                               
 
860
                                                                                        foundedge=1;
 
861
                                                                                }
 
862
                                                                        }
 
863
                                                                        else if(!(efa->e2->v1->f & 2) && !(efa->e2->v2->f & 2)){ // xxxx
 
864
                                                                                if(efa->e2->h==0){
 
865
                                                                                        opposite=efa->e2;
 
866
                                                                                        foundedge=1;
 
867
                                                                                }
 
868
                                                                        }
 
869
                                                                        else if(!(efa->e3->v1->f & 2) && !(efa->e3->v2->f & 2)){
 
870
                                                                                if(efa->e3->h==0){
 
871
                                                                                        opposite=efa->e3;
 
872
                                                                                        foundedge=1;
 
873
                                                                                }
 
874
                                                                        }
 
875
                                                                        else if(!(efa->e4->v1->f & 2) && !(efa->e4->v2->f & 2)){
 
876
                                                                                if(efa->e4->h==0){
 
877
                                                                                        opposite=efa->e4;
 
878
                                                                                        foundedge=1;
 
879
                                                                                }
 
880
                                                                        }
 
881
                                                                        
 
882
                                                                        if(foundedge){
 
883
                                                                                currentvl=efa;
 
884
                                                                                formervl=efa;
 
885
                                                                        
 
886
                                                                                /* mark this side of the edge so we know in which direction we went */
 
887
                                                                                if(side==1) efa->f1 |= 4;
 
888
                                                                        }
 
889
                                                                }
 
890
                                                        }
 
891
                                                        else {  
 
892
                                                                if(efa!=formervl){      /* prevent going backwards in the loop */
 
893
                                                                
 
894
                                                                        if(!(efa->e1->v1->f & 2) && !(efa->e1->v2->f & 2)){
 
895
                                                                                if(efa->e1->h==0){
 
896
                                                                                        opposite=efa->e1;                                                                                                               
 
897
                                                                                        foundedge=1;
 
898
                                                                                }
 
899
                                                                        }
 
900
                                                                        else if(!(efa->e2->v1->f & 2) && !(efa->e2->v2->f & 2)){
 
901
                                                                                if(efa->e2->h==0){
 
902
                                                                                        opposite=efa->e2;
 
903
                                                                                        foundedge=1;
 
904
                                                                                }
 
905
                                                                        }
 
906
                                                                        else if(!(efa->e3->v1->f & 2) && !(efa->e3->v2->f & 2)){
 
907
                                                                                if(efa->e3->h==0){
 
908
                                                                                        opposite=efa->e3;
 
909
                                                                                        foundedge=1;
 
910
                                                                                }
 
911
                                                                        }
 
912
                                                                        else if(!(efa->e4->v1->f & 2) && !(efa->e4->v2->f & 2)){
 
913
                                                                                if(efa->e4->h==0){
 
914
                                                                                        opposite=efa->e4;
 
915
                                                                                        foundedge=1;
 
916
                                                                                }
 
917
                                                                        }
 
918
                                                                        
 
919
                                                                        currentvl=efa;
 
920
                                                                }
 
921
                                                        }
 
922
                                                }
 
923
                                        }
 
924
                                efa=efa->next;
 
925
                                }
 
926
                                /*----------END Get Loop------------------------*/
 
927
                                
 
928
                        
 
929
                                /*----------Decisions-----------------------------*/
 
930
                                if(foundedge){
 
931
                                        /* mark the edge and face as done */                                    
 
932
                                        currente->f2 |= 8;
 
933
                                        currentvl->f1 |= 8;
 
934
 
 
935
                                        if(opposite->f2 & 4) lastface=1;        /* found the starting edge! close loop */                                                               
 
936
                                        else{
 
937
                                                /* un-set the testflags */
 
938
                                                currente->f2 &= ~2;
 
939
                                                currente->v1->f &= ~2; // xxxx
 
940
                                                currente->v2->f &= ~2;                                                  
 
941
                                                
 
942
                                                /* set the opposite edge to be the current edge */                              
 
943
                                                currente=opposite;                                                      
 
944
                                                
 
945
                                                /* set the current face to be the FORMER face (to prevent going backwards in the loop) */
 
946
                                                formervl=currentvl;
 
947
                                                
 
948
                                                /* set the testflags */
 
949
                                                currente->f2 |= 2;
 
950
                                                currente->v1->f |= 2; // xxxx
 
951
                                                currente->v2->f |= 2;                   
 
952
                                        }
 
953
                                        c++;
 
954
                                }
 
955
                                else{   
 
956
                                        /* un-set the testflags */
 
957
                                        currente->f2 &= ~2;
 
958
                                        currente->v1->f &= ~2; // xxxx
 
959
                                        currente->v2->f &= ~2;
 
960
                                        
 
961
                                        /* mark the edge and face as done */
 
962
                                        currente->f2 |= 8;
 
963
                                        currentvl->f1 |= 8;
 
964
                                        
 
965
                                        
 
966
                                                                                                
 
967
                                        /* is the the first time we've ran out of possible faces?
 
968
                                        *  try to start from the beginning but in the opposite direction go as far as possible
 
969
                                        */                              
 
970
                                        if(side==1){                                            
 
971
                                                if(tri)tri=0;
 
972
                                                currente=start;
 
973
                                                currente->f2 |= 2;
 
974
                                                currente->v1->f |= 2; // xxxx
 
975
                                                currente->v2->f |= 2;                                   
 
976
                                                side++;
 
977
                                                c=0;
 
978
                                        }
 
979
                                        else lastface=1;
 
980
                                }                               
 
981
                                /*----------END Decisions-----------------------------*/
 
982
                                
 
983
                        }
 
984
                        /*-----END Limit the Search----- */
 
985
                        
 
986
                        
 
987
                        /*------------- Preview lines--------------- */
 
988
                        
 
989
                        /* uses callback mechanism to draw it all in current area */
 
990
                        scrarea_do_windraw(curarea);                    
 
991
                        
 
992
                        /* set window matrix to perspective, default an area returns with buttons transform */
 
993
                        persp(PERSP_VIEW);
 
994
                        /* make a copy, for safety */
 
995
                        glPushMatrix();
 
996
                        /* multiply with the object transformation */
 
997
                        mymultmatrix(G.obedit->obmat);
 
998
                        
 
999
                        glColor3ub(255, 255, 0);
 
1000
                        
 
1001
                        if(mode==LOOP_SELECT){
 
1002
                                efa= em->faces.first;
 
1003
                                while(efa){
 
1004
                                        if(efa->f1 & 8){
 
1005
                                                
 
1006
                                                if(!(efa->e1->f2 & 8)){
 
1007
                                                        glBegin(GL_LINES);                                                      
 
1008
                                                        glVertex3fv(efa->e1->v1->co);
 
1009
                                                        glVertex3fv(efa->e1->v2->co);
 
1010
                                                        glEnd();        
 
1011
                                                }
 
1012
                                                
 
1013
                                                if(!(efa->e2->f2 & 8)){
 
1014
                                                        glBegin(GL_LINES);                                                      
 
1015
                                                        glVertex3fv(efa->e2->v1->co);
 
1016
                                                        glVertex3fv(efa->e2->v2->co);
 
1017
                                                        glEnd();        
 
1018
                                                }
 
1019
                                                
 
1020
                                                if(!(efa->e3->f2 & 8)){
 
1021
                                                        glBegin(GL_LINES);                                                      
 
1022
                                                        glVertex3fv(efa->e3->v1->co);
 
1023
                                                        glVertex3fv(efa->e3->v2->co);
 
1024
                                                        glEnd();        
 
1025
                                                }
 
1026
                                                
 
1027
                                                if(efa->e4){
 
1028
                                                        if(!(efa->e4->f2 & 8)){
 
1029
                                                                glBegin(GL_LINES);                                                      
 
1030
                                                                glVertex3fv(efa->e4->v1->co);
 
1031
                                                                glVertex3fv(efa->e4->v2->co);
 
1032
                                                                glEnd();        
 
1033
                                                        }
 
1034
                                                }
 
1035
                                        }
 
1036
                                        efa=efa->next;
 
1037
                                }
 
1038
                        }
 
1039
                                
 
1040
                        if(mode==LOOP_CUT){
 
1041
                                efa= em->faces.first;
 
1042
                                while(efa){
 
1043
                                        if(efa->f1 & 8){
 
1044
                                                float cen[2][3];
 
1045
                                                int a=0;                                                
 
1046
                                                
 
1047
                                                efa->v1->f &= ~8; // xxx
 
1048
                                                efa->v2->f &= ~8;
 
1049
                                                efa->v3->f &= ~8;
 
1050
                                                if(efa->v4)efa->v4->f &= ~8;
 
1051
                                        
 
1052
                                                if(efa->e1->f2 & 8){
 
1053
                                                        cen[a][0]= (efa->e1->v1->co[0] + efa->e1->v2->co[0])/2.0;
 
1054
                                                        cen[a][1]= (efa->e1->v1->co[1] + efa->e1->v2->co[1])/2.0;
 
1055
                                                        cen[a][2]= (efa->e1->v1->co[2] + efa->e1->v2->co[2])/2.0;
 
1056
                                                        
 
1057
                                                        efa->e1->v1->f |= 8; // xxx
 
1058
                                                        efa->e1->v2->f |= 8;
 
1059
                                                        
 
1060
                                                        a++;
 
1061
                                                }
 
1062
                                                if((efa->e2->f2 & 8) && a!=2){
 
1063
                                                        cen[a][0]= (efa->e2->v1->co[0] + efa->e2->v2->co[0])/2.0;
 
1064
                                                        cen[a][1]= (efa->e2->v1->co[1] + efa->e2->v2->co[1])/2.0;
 
1065
                                                        cen[a][2]= (efa->e2->v1->co[2] + efa->e2->v2->co[2])/2.0;
 
1066
                                                        
 
1067
                                                        efa->e2->v1->f |= 8; // xxx
 
1068
                                                        efa->e2->v2->f |= 8;
 
1069
                                                        
 
1070
                                                        a++;
 
1071
                                                }
 
1072
                                                if((efa->e3->f2 & 8) && a!=2){
 
1073
                                                        cen[a][0]= (efa->e3->v1->co[0] + efa->e3->v2->co[0])/2.0;
 
1074
                                                        cen[a][1]= (efa->e3->v1->co[1] + efa->e3->v2->co[1])/2.0;
 
1075
                                                        cen[a][2]= (efa->e3->v1->co[2] + efa->e3->v2->co[2])/2.0;
 
1076
                                                        
 
1077
                                                        efa->e3->v1->f |= 8; // xxx
 
1078
                                                        efa->e3->v2->f |= 8;
 
1079
                                                        
 
1080
                                                        a++;
 
1081
                                                }
 
1082
                                                
 
1083
                                                if(efa->e4){
 
1084
                                                        if((efa->e4->f2 & 8) && a!=2){
 
1085
                                                                cen[a][0]= (efa->e4->v1->co[0] + efa->e4->v2->co[0])/2.0;
 
1086
                                                                cen[a][1]= (efa->e4->v1->co[1] + efa->e4->v2->co[1])/2.0;
 
1087
                                                                cen[a][2]= (efa->e4->v1->co[2] + efa->e4->v2->co[2])/2.0;
 
1088
                                                                
 
1089
                                                                efa->e4->v1->f |= 8; // xxx
 
1090
                                                                efa->e4->v2->f |= 8;
 
1091
                                                        
 
1092
                                                                a++;
 
1093
                                                        }
 
1094
                                                }
 
1095
                                                else{   /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */                                                                                                            
 
1096
                                                                if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
 
1097
                                                                        cen[a][0]= efa->v1->co[0];
 
1098
                                                                        cen[a][1]= efa->v1->co[1];
 
1099
                                                                        cen[a][2]= efa->v1->co[2];
 
1100
                                                                        a++;                                                            
 
1101
                                                                }
 
1102
                                                                else if(!(efa->v2->f & 8) && efa->v2->h==0){
 
1103
                                                                        cen[a][0]= efa->v2->co[0];
 
1104
                                                                        cen[a][1]= efa->v2->co[1];
 
1105
                                                                        cen[a][2]= efa->v2->co[2];      
 
1106
                                                                        a++;
 
1107
                                                                }
 
1108
                                                                else if(!(efa->v3->f & 8) && efa->v3->h==0){
 
1109
                                                                        cen[a][0]= efa->v3->co[0];
 
1110
                                                                        cen[a][1]= efa->v3->co[1];
 
1111
                                                                        cen[a][2]= efa->v3->co[2];
 
1112
                                                                        a++;                                                                    
 
1113
                                                                }                                                       
 
1114
                                                }
 
1115
                                                
 
1116
                                                if(a==2){
 
1117
                                                        glBegin(GL_LINES);
 
1118
                                                        
 
1119
                                                        glVertex3fv(cen[0]);
 
1120
                                                        glVertex3fv(cen[1]);    
 
1121
                                                                                                
 
1122
                                                        glEnd();
 
1123
                                                }                                               
 
1124
                                        }
 
1125
                                        efa=efa->next;
 
1126
                                }
 
1127
                                
 
1128
                                eed=em->edges.first; 
 
1129
                                while(eed){
 
1130
                                        if(eed->f2 & 64){
 
1131
                                                glBegin(GL_LINES);
 
1132
                                                glColor3ub(200, 255, 200);
 
1133
                                                glVertex3fv(eed->v1->co);
 
1134
                                                glVertex3fv(eed->v2->co);
 
1135
                                                glEnd();
 
1136
                                                eed=0;
 
1137
                                        }else{
 
1138
                                                eed = eed->next;
 
1139
                                        }
 
1140
                                }               
 
1141
                        }
 
1142
                        
 
1143
                        /* restore matrix transform */
 
1144
                        glPopMatrix();
 
1145
                        
 
1146
                        headerprint("LMB to confirm, RMB to cancel");
 
1147
                        
 
1148
                        /* this also verifies other area/windows for clean swap */
 
1149
                        screen_swapbuffers();
 
1150
                        
 
1151
                        /* backbuffer refresh for non-apples (no aux) */
 
1152
#ifndef __APPLE__
 
1153
                        if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
 
1154
                                backdrawview3d(0);
 
1155
                        }
 
1156
#endif
 
1157
        
 
1158
                        /*--------- END Preview Lines------------*/
 
1159
                                
 
1160
                }/*if(start!=NULL){ */
 
1161
                else PIL_sleep_ms(10);  // idle
 
1162
                
 
1163
                while(qtest()) {
 
1164
                        unsigned short val=0;                   
 
1165
                        event= extern_qread(&val);      /* extern_qread stores important events for the mainloop to handle */
 
1166
 
 
1167
                        /* val==0 on key-release event */
 
1168
                        if(val && (event==ESCKEY || event==RIGHTMOUSE || event==LEFTMOUSE || event==RETKEY || event == MIDDLEMOUSE)){
 
1169
                                searching=0;
 
1170
                        }
 
1171
                }       
 
1172
                
 
1173
        }/*while(event!=ESCKEY && event!=RIGHTMOUSE && event!=LEFTMOUSE && event!=RETKEY){*/
 
1174
        
 
1175
        /*----------Select Loop------------*/
 
1176
        if(mode==LOOP_SELECT && start!=NULL && ((event==LEFTMOUSE || event==RETKEY) || event == MIDDLEMOUSE || event == BKEY)){
 
1177
                                
 
1178
                /* If this is a unmodified select, clear the selection */
 
1179
                if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){
 
1180
                        for(efa= em->faces.first;efa;efa=efa->next){
 
1181
                                EM_select_face(efa, 0); // and this is correct deselect face            
 
1182
                        }
 
1183
                }
 
1184
                /* Alt was not pressed, so add to the selection */
 
1185
                if(!(G.qual & LR_ALTKEY)){
 
1186
                        for(efa= em->faces.first;efa;efa=efa->next){
 
1187
                                if(efa->f1 & 8){
 
1188
                                        EM_select_face(efa, 1); // and this is correct select face
 
1189
                                }
 
1190
                        }
 
1191
                }
 
1192
                /* alt was pressed, so subtract from the selection */
 
1193
                else
 
1194
                {
 
1195
                        for(efa= em->faces.first;efa;efa=efa->next){
 
1196
                                if(efa->f1 & 8){
 
1197
                                        EM_select_face(efa, 0); // this is correct deselect face
 
1198
                                }
 
1199
                        }
 
1200
                }
 
1201
        
 
1202
        }
 
1203
        /*----------END Select Loop------------*/
 
1204
        
 
1205
        /*----------Cut Loop---------------*/                   
 
1206
        if(mode==LOOP_CUT && start!=NULL && (event==LEFTMOUSE || event==RETKEY)){
 
1207
                
 
1208
                /* count the number of edges in the loop */             
 
1209
                for(eed=em->edges.first; eed; eed = eed->next){
 
1210
                        if(eed->f2 & 8)
 
1211
                                ect++;
 
1212
                }               
 
1213
                
 
1214
                tagged = MEM_mallocN(ect*sizeof(EditEdge*), "tagged");
 
1215
                taggedsrch = MEM_mallocN(ect*sizeof(EditEdge*), "taggedsrch");
 
1216
                for(i=0;i<ect;i++)
 
1217
                {
 
1218
                        tagged[i] = NULL;
 
1219
                        taggedsrch[i] = NULL;
 
1220
                }
 
1221
                ect = 0;
 
1222
                for(eed=em->edges.first; eed; eed = eed->next){
 
1223
                        if(eed->f2 & 8)
 
1224
                        {
 
1225
                                if(eed->h==0){
 
1226
                                        eed->v1->f |= SELECT;
 
1227
                                        eed->v2->f |= SELECT;
 
1228
                                        eed->f |= SELECT;
 
1229
                                        tagged[ect] = eed;
 
1230
                                        eed->f2 &= ~(32);
 
1231
                                        ect++;
 
1232
                                }
 
1233
                        }                       
 
1234
                }
 
1235
                taggedsrch[0] = tagged[0];
 
1236
 
 
1237
                while(timesthrough < 2)
 
1238
                {
 
1239
                        i=0;
 
1240
                        while(i < ect){/*Look at the members of the search array to line up cuts*/
 
1241
                                if(taggedsrch[i]==NULL)break;
 
1242
                                for(j=0;j<ect;j++){                      /*Look through the list of tagged verts for connected edges*/
 
1243
                                        int addededge = 0;
 
1244
                                        if(taggedsrch[i]->f2 & 32)        /*If this edgee is marked as flipped, use vert 2*/
 
1245
                                                look = taggedsrch[i]->v2;
 
1246
                                        else                                                     /*else use vert 1*/
 
1247
                                                look = taggedsrch[i]->v1;
 
1248
 
 
1249
                                        if(taggedsrch[i] == tagged[j])
 
1250
                                                continue;  /*If we are looking at the same edge, skip it*/
 
1251
        
 
1252
                                        skip = 0;
 
1253
                                        for(k=0;k<ect;k++)      {
 
1254
                                                if(taggedsrch[k] == NULL)       /*go to empty part of search list without finding*/
 
1255
                                                        break;                                                  
 
1256
                                                if(tagged[j] == taggedsrch[k]){         /*We found a match already in the list*/
 
1257
                                                        skip = 1;
 
1258
                                                        break;
 
1259
                                                }
 
1260
                                        }
 
1261
                                        if(skip)
 
1262
                                                continue;
 
1263
                                        nextpos = 0;
 
1264
                                        if(findedgelist(look,tagged[j]->v2)){
 
1265
                                                while(nextpos < ect){ /*Find the first open spot in the search array*/
 
1266
                                                        if(taggedsrch[nextpos] == NULL){
 
1267
                                                                taggedsrch[nextpos] = tagged[j]; /*put tagged[j] in it*/
 
1268
                                                                taggedsrch[nextpos]->f2 |= 32;
 
1269
                                                                addededge = 1;
 
1270
                                                                break;
 
1271
                                                        }
 
1272
                                                        else
 
1273
                                                                nextpos++;
 
1274
                                                }
 
1275
                                        } /* End else if connected to vert 2*/
 
1276
                                        else if(findedgelist(look,tagged[j]->v1)){   /*If our vert is connected to vert 1 */
 
1277
                                                while(nextpos < ect){ /*Find the first open spot in the search array */
 
1278
                                                        if(taggedsrch[nextpos] == NULL){
 
1279
                                                                taggedsrch[nextpos] = tagged[j]; /*put tagged[j] in it*/
 
1280
                                                                addededge = 1;
 
1281
                                                                break;
 
1282
                                                        }
 
1283
                                                        else 
 
1284
                                                                nextpos++;
 
1285
                                                }
 
1286
                                        }
 
1287
 
 
1288
                                        if(addededge)
 
1289
                                        {
 
1290
                                                break;
 
1291
                                        }                                       
 
1292
                                }/* End Outer For (j)*/
 
1293
                                i++;
 
1294
                        } /* End while(j<ect)*/
 
1295
                        timesthrough++;
 
1296
                } /*end while timesthrough */
 
1297
                percentcut = 0.50;
 
1298
                searching = 1;
 
1299
                cut   = 1;
 
1300
                smooth = 0;
 
1301
                close = NULL;
 
1302
 
 
1303
 
 
1304
                /* Count the Number of Faces in the selected loop*/
 
1305
                percentfaces = 0;
 
1306
                for(efa= em->faces.first; efa ;efa=efa->next){
 
1307
                        if(efa->f1 & 8)
 
1308
                         {
 
1309
                                percentfaces++; 
 
1310
                         }
 
1311
                }
 
1312
                        
 
1313
                /* create a dynamic array for those face pointers */
 
1314
                percentfacesloop = MEM_mallocN(percentfaces*sizeof(EditFace*), "percentage");
 
1315
 
 
1316
                /* put those faces in the array */
 
1317
                i=0;
 
1318
                for(efa= em->faces.first; efa ;efa=efa->next){
 
1319
                         if(efa->f1 & 8)
 
1320
                         {
 
1321
                                percentfacesloop[i] = efa;      
 
1322
                                i++;
 
1323
                         }
 
1324
                }
 
1325
 
 
1326
                while(searching){
 
1327
                        
 
1328
                        /* For the % calculation */
 
1329
                        short mval[2];                  
 
1330
                        float labda, rc[2], len, slen=0.0;
 
1331
                        float v1[2], v2[2], v3[2];
 
1332
 
 
1333
                        /*------------- Percent Cut Preview Lines--------------- */
 
1334
                        scrarea_do_windraw(curarea);                    
 
1335
                        persp(PERSP_VIEW);
 
1336
                        glPushMatrix();
 
1337
                        mymultmatrix(G.obedit->obmat);
 
1338
                        glColor3ub(0, 255, 255);
 
1339
                                
 
1340
                        /*Put the preview lines where they should be for the percentage selected.*/
 
1341
 
 
1342
                        for(i=0;i<percentfaces;i++){
 
1343
                                efa = percentfacesloop[i];
 
1344
                                for(eed = em->edges.first; eed; eed=eed->next){
 
1345
                                        if(eed->f2 & 64){       /* color the starting edge */                   
 
1346
                                                glBegin(GL_LINES);
 
1347
                                                                                                
 
1348
                                                glColor3ub(200, 255, 200);
 
1349
                                                glVertex3fv(eed->v1->co);                                       
 
1350
                                                glVertex3fv(eed->v2->co);
 
1351
                                                
 
1352
                                                glEnd();
 
1353
 
 
1354
                                                glPointSize(5);
 
1355
                                                glBegin(GL_POINTS);
 
1356
                                                glColor3ub(255,0,255);
 
1357
                                                
 
1358
                                                if(eed->f2 & 32)
 
1359
                                                        glVertex3fv(eed->v2->co);                       
 
1360
                                                else
 
1361
                                                        glVertex3fv(eed->v1->co);
 
1362
                                                glEnd();
 
1363
 
 
1364
 
 
1365
                                                /*Get Starting Edge Length*/
 
1366
                                                slen = sqrt((eed->v1->co[0]-eed->v2->co[0])*(eed->v1->co[0]-eed->v2->co[0])+
 
1367
                                                                        (eed->v1->co[1]-eed->v2->co[1])*(eed->v1->co[1]-eed->v2->co[1])+
 
1368
                                                                        (eed->v1->co[2]-eed->v2->co[2])*(eed->v1->co[2]-eed->v2->co[2]));
 
1369
                                        }
 
1370
                                }
 
1371
                                
 
1372
                                if(!inset){
 
1373
                                        glColor3ub(0,255,255);
 
1374
                                        if(efa->f1 & 8)
 
1375
                                        {
 
1376
                                                float cen[2][3];
 
1377
                                                int a=0;                                        
 
1378
                                                
 
1379
                                                efa->v1->f &= ~8; // xxx
 
1380
                                                efa->v2->f &= ~8;
 
1381
                                                efa->v3->f &= ~8;
 
1382
                                                if(efa->v4)efa->v4->f &= ~8;
 
1383
                                                
 
1384
                                                if(efa->e1->f2 & 8){
 
1385
                                                        float pct;
 
1386
                                                        if(efa->e1->f2 & 32)
 
1387
                                                                pct = 1-percentcut;
 
1388
                                                        else
 
1389
                                                                pct = percentcut;
 
1390
                                                        cen[a][0]= efa->e1->v1->co[0] - ((efa->e1->v1->co[0] - efa->e1->v2->co[0]) * (pct));
 
1391
                                                        cen[a][1]= efa->e1->v1->co[1] - ((efa->e1->v1->co[1] - efa->e1->v2->co[1]) * (pct));
 
1392
                                                        cen[a][2]= efa->e1->v1->co[2] - ((efa->e1->v1->co[2] - efa->e1->v2->co[2]) * (pct));
 
1393
                                                        efa->e1->v1->f |= 8; // xxx
 
1394
                                                        efa->e1->v2->f |= 8;
 
1395
                                                        a++;
 
1396
                                                }
 
1397
                                                if((efa->e2->f2 & 8) && a!=2)
 
1398
                                                {
 
1399
                                                        float pct;
 
1400
                                                        if(efa->e2->f2 & 32)
 
1401
                                                                pct = 1-percentcut;
 
1402
                                                        else
 
1403
                                                                pct = percentcut;
 
1404
                                                        cen[a][0]= efa->e2->v1->co[0] - ((efa->e2->v1->co[0] - efa->e2->v2->co[0]) * (pct));
 
1405
                                                        cen[a][1]= efa->e2->v1->co[1] - ((efa->e2->v1->co[1] - efa->e2->v2->co[1]) * (pct));
 
1406
                                                        cen[a][2]= efa->e2->v1->co[2] - ((efa->e2->v1->co[2] - efa->e2->v2->co[2]) * (pct));
 
1407
 
 
1408
                                                        efa->e2->v1->f |= 8; // xxx
 
1409
                                                        efa->e2->v2->f |= 8;
 
1410
                                                        
 
1411
                                                        a++;
 
1412
                                                }
 
1413
                                                if((efa->e3->f2 & 8) && a!=2){
 
1414
                                                        float pct;
 
1415
                                                        if(efa->e3->f2 & 32)
 
1416
                                                                pct = 1-percentcut;
 
1417
                                                        else
 
1418
                                                                pct = percentcut;
 
1419
                                                        cen[a][0]= efa->e3->v1->co[0] - ((efa->e3->v1->co[0] - efa->e3->v2->co[0]) * (pct));
 
1420
                                                        cen[a][1]= efa->e3->v1->co[1] - ((efa->e3->v1->co[1] - efa->e3->v2->co[1]) * (pct));
 
1421
                                                        cen[a][2]= efa->e3->v1->co[2] - ((efa->e3->v1->co[2] - efa->e3->v2->co[2]) * (pct));
 
1422
 
 
1423
                                                        efa->e3->v1->f |= 8; // xxx
 
1424
                                                        efa->e3->v2->f |= 8;
 
1425
                                                        
 
1426
                                                        a++;
 
1427
                                                }
 
1428
                                                        
 
1429
                                                if(efa->e4){
 
1430
                                                        if((efa->e4->f2 & 8) && a!=2){
 
1431
                                                                float pct;
 
1432
                                                                if(efa->e4->f2 & 32)
 
1433
                                                                        pct = 1-percentcut;
 
1434
                                                                else
 
1435
                                                                        pct = percentcut;
 
1436
                                                                cen[a][0]= efa->e4->v1->co[0] - ((efa->e4->v1->co[0] - efa->e4->v2->co[0]) * (pct));
 
1437
                                                                cen[a][1]= efa->e4->v1->co[1] - ((efa->e4->v1->co[1] - efa->e4->v2->co[1]) * (pct));
 
1438
                                                                cen[a][2]= efa->e4->v1->co[2] - ((efa->e4->v1->co[2] - efa->e4->v2->co[2]) * (pct));
 
1439
 
 
1440
                                                                efa->e4->v1->f |= 8; // xxx
 
1441
                                                                efa->e4->v2->f |= 8;
 
1442
                                                        
 
1443
                                                                a++;
 
1444
                                                        }
 
1445
                                                }
 
1446
                                                else {  /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */
 
1447
                                                        if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
 
1448
                                                                cen[a][0]= efa->v1->co[0];
 
1449
                                                                cen[a][1]= efa->v1->co[1];
 
1450
                                                                cen[a][2]= efa->v1->co[2];
 
1451
                                                                a++;                                                            
 
1452
                                                        }
 
1453
                                                        else if(!(efa->v2->f & 8) && efa->v2->h==0){ // xxx
 
1454
                                                                cen[a][0]= efa->v2->co[0];
 
1455
                                                                cen[a][1]= efa->v2->co[1];
 
1456
                                                                cen[a][2]= efa->v2->co[2];
 
1457
                                                                a++;                                                            
 
1458
                                                        }
 
1459
                                                        else if(!(efa->v3->f & 8) && efa->v3->h==0){ // xxx
 
1460
                                                                cen[a][0]= efa->v3->co[0];
 
1461
                                                                cen[a][1]= efa->v3->co[1];
 
1462
                                                                cen[a][2]= efa->v3->co[2];
 
1463
                                                                a++;                                                                                                    
 
1464
                                                        }
 
1465
                                                }
 
1466
                                                
 
1467
                                                if(a==2){
 
1468
                                                        glBegin(GL_LINES);
 
1469
                                                        
 
1470
                                                        glVertex3fv(cen[0]);
 
1471
                                                        glVertex3fv(cen[1]);    
 
1472
                                                                                                
 
1473
                                                        glEnd();
 
1474
                                                }       
 
1475
                                        }
 
1476
                                }/* end preview line drawing */                 
 
1477
                                else{
 
1478
                                        glColor3ub(0,128,255);
 
1479
                                        if(efa->f1 & 8)
 
1480
                                        {
 
1481
                                                float cen[2][3];
 
1482
                                                int a=0;                                        
 
1483
                                                
 
1484
                                                efa->v1->f &= ~8; // xxx
 
1485
                                                efa->v2->f &= ~8;
 
1486
                                                efa->v3->f &= ~8;
 
1487
                                                if(efa->v4)efa->v4->f &= ~8;
 
1488
                                                
 
1489
                                                if(efa->e1->f2 & 8){                                                    
 
1490
                                                        float nlen,npct;
 
1491
                                                        
 
1492
                                                        nlen = sqrt((efa->e1->v1->co[0] - efa->e1->v2->co[0])*(efa->e1->v1->co[0] - efa->e1->v2->co[0])+
 
1493
                                                                                (efa->e1->v1->co[1] - efa->e1->v2->co[1])*(efa->e1->v1->co[1] - efa->e1->v2->co[1])+
 
1494
                                                                                (efa->e1->v1->co[2] - efa->e1->v2->co[2])*(efa->e1->v1->co[2] - efa->e1->v2->co[2]));
 
1495
                                                        npct = (percentcut*slen)/nlen;
 
1496
                                                        if(npct >= 1) npct = 1;
 
1497
                                                        if(efa->e1->f2 & 32)    npct = 1-npct;
 
1498
 
 
1499
                                                        cen[a][0]= efa->e1->v1->co[0] - ((efa->e1->v1->co[0] - efa->e1->v2->co[0]) * (npct));
 
1500
                                                        cen[a][1]= efa->e1->v1->co[1] - ((efa->e1->v1->co[1] - efa->e1->v2->co[1]) * (npct));
 
1501
                                                        cen[a][2]= efa->e1->v1->co[2] - ((efa->e1->v1->co[2] - efa->e1->v2->co[2]) * (npct));
 
1502
 
 
1503
                                                        efa->e1->f1 = 32768*(npct);
 
1504
                                                        efa->e1->v1->f |= 8; // xxx
 
1505
                                                        efa->e1->v2->f |= 8;
 
1506
                                                        a++;
 
1507
                                                }
 
1508
                                                if((efa->e2->f2 & 8) && a!=2)
 
1509
                                                {
 
1510
                                                        float nlen,npct;
 
1511
                                                        
 
1512
                                                        nlen = sqrt((efa->e2->v1->co[0] - efa->e2->v2->co[0])*(efa->e2->v1->co[0] - efa->e2->v2->co[0])+
 
1513
                                                                                (efa->e2->v1->co[1] - efa->e2->v2->co[1])*(efa->e2->v1->co[1] - efa->e2->v2->co[1])+
 
1514
                                                                                (efa->e2->v1->co[2] - efa->e2->v2->co[2])*(efa->e2->v1->co[2] - efa->e2->v2->co[2]));
 
1515
                                                        npct = (percentcut*slen)/nlen;
 
1516
                                                        if(npct >= 1) npct = 1;
 
1517
                                                        if(efa->e2->f2 & 32)    npct = 1-npct;
 
1518
 
 
1519
                                                        cen[a][0]= efa->e2->v1->co[0] - ((efa->e2->v1->co[0] - efa->e2->v2->co[0]) * (npct));
 
1520
                                                        cen[a][1]= efa->e2->v1->co[1] - ((efa->e2->v1->co[1] - efa->e2->v2->co[1]) * (npct));
 
1521
                                                        cen[a][2]= efa->e2->v1->co[2] - ((efa->e2->v1->co[2] - efa->e2->v2->co[2]) * (npct));
 
1522
 
 
1523
                                                        efa->e2->f1 = 32768*(npct);                                                             
 
1524
                                                        efa->e2->v1->f |= 8; // xxx
 
1525
                                                        efa->e2->v2->f |= 8;
 
1526
                                                        a++;
 
1527
                                                }
 
1528
                                                if((efa->e3->f2 & 8) && a!=2){
 
1529
                                                        float nlen,npct;
 
1530
                                                        
 
1531
                                                        nlen = sqrt((efa->e3->v1->co[0] - efa->e3->v2->co[0])*(efa->e3->v1->co[0] - efa->e3->v2->co[0])+
 
1532
                                                                                (efa->e3->v1->co[1] - efa->e3->v2->co[1])*(efa->e3->v1->co[1] - efa->e3->v2->co[1])+
 
1533
                                                                                (efa->e3->v1->co[2] - efa->e3->v2->co[2])*(efa->e3->v1->co[2] - efa->e3->v2->co[2]));
 
1534
                                                        npct = (percentcut*slen)/nlen;
 
1535
                                                        if(npct >= 1) npct = 1;
 
1536
                                                        if(efa->e3->f2 & 32)    npct = 1-npct;
 
1537
 
 
1538
                                                        cen[a][0]= efa->e3->v1->co[0] - ((efa->e3->v1->co[0] - efa->e3->v2->co[0]) * (npct));
 
1539
                                                        cen[a][1]= efa->e3->v1->co[1] - ((efa->e3->v1->co[1] - efa->e3->v2->co[1]) * (npct));
 
1540
                                                        cen[a][2]= efa->e3->v1->co[2] - ((efa->e3->v1->co[2] - efa->e3->v2->co[2]) * (npct));
 
1541
 
 
1542
                                                        efa->e3->f1 = 32768*(npct);                                                             
 
1543
                                                        efa->e3->v1->f |= 8; // xxx
 
1544
                                                        efa->e3->v2->f |= 8;
 
1545
                                                        a++;
 
1546
                                                }
 
1547
                                                        
 
1548
                                                if(efa->e4){
 
1549
                                                        if((efa->e4->f2 & 8) && a!=2){
 
1550
                                                                float nlen,npct;
 
1551
                                                                
 
1552
                                                                nlen = sqrt((efa->e4->v1->co[0] - efa->e4->v2->co[0])*(efa->e4->v1->co[0] - efa->e4->v2->co[0])+
 
1553
                                                                                        (efa->e4->v1->co[1] - efa->e4->v2->co[1])*(efa->e4->v1->co[1] - efa->e4->v2->co[1])+
 
1554
                                                                                        (efa->e4->v1->co[2] - efa->e4->v2->co[2])*(efa->e4->v1->co[2] - efa->e4->v2->co[2]));
 
1555
                                                        npct = (percentcut*slen)/nlen;
 
1556
                                                        if(npct >= 1) npct = 1;
 
1557
                                                        if(efa->e4->f2 & 32)    npct = 1-npct;
 
1558
 
 
1559
                                                                cen[a][0]= efa->e4->v1->co[0] - ((efa->e4->v1->co[0] - efa->e4->v2->co[0]) * (npct));
 
1560
                                                                cen[a][1]= efa->e4->v1->co[1] - ((efa->e4->v1->co[1] - efa->e4->v2->co[1]) * (npct));
 
1561
                                                                cen[a][2]= efa->e4->v1->co[2] - ((efa->e4->v1->co[2] - efa->e4->v2->co[2]) * (npct));
 
1562
 
 
1563
                                                                efa->e4->f1 = 32768*(npct);                                                                     
 
1564
                                                                efa->e4->v1->f |= 8; // xxx
 
1565
                                                                efa->e4->v2->f |= 8;
 
1566
                                                                a++;
 
1567
                                                        }
 
1568
                                                }
 
1569
                                                else {  /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */
 
1570
                                                        if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
 
1571
                                                                cen[a][0]= efa->v1->co[0];
 
1572
                                                                cen[a][1]= efa->v1->co[1];
 
1573
                                                                cen[a][2]= efa->v1->co[2];
 
1574
                                                                a++;                                                            
 
1575
                                                        }
 
1576
                                                        else if(!(efa->v2->f & 8) && efa->v2->h==0){ // xxx
 
1577
                                                                cen[a][0]= efa->v2->co[0];
 
1578
                                                                cen[a][1]= efa->v2->co[1];
 
1579
                                                                cen[a][2]= efa->v2->co[2];
 
1580
                                                                a++;                                                            
 
1581
                                                        }
 
1582
                                                        else if(!(efa->v3->f & 8) && efa->v3->h==0){ // xxx
 
1583
                                                                cen[a][0]= efa->v3->co[0];
 
1584
                                                                cen[a][1]= efa->v3->co[1];
 
1585
                                                                cen[a][2]= efa->v3->co[2];
 
1586
                                                                a++;                                                                                                    
 
1587
                                                        }
 
1588
                                                }
 
1589
                                                
 
1590
                                                if(a==2){
 
1591
                                                        glBegin(GL_LINES);
 
1592
                                                        
 
1593
                                                        glVertex3fv(cen[0]);
 
1594
                                                        glVertex3fv(cen[1]);    
 
1595
                                                                                                
 
1596
                                                        glEnd();
 
1597
                                                }       
 
1598
                                        }
 
1599
                                }
 
1600
                        }
 
1601
                        /* restore matrix transform */
 
1602
        
 
1603
                        glPopMatrix();
 
1604
 
 
1605
                        /*--------- END Preview Lines------------*/
 
1606
                        while(qtest()) 
 
1607
                        {
 
1608
                                unsigned short val=0;                   
 
1609
                                event= extern_qread(&val);      /* extern_qread stores important events for the mainloop to handle */
 
1610
                                /* val==0 on key-release event */
 
1611
                
 
1612
                                if(val && (event==SKEY))
 
1613
                                {
 
1614
                                        if(smooth)smooth = 0;
 
1615
                                        else smooth = 1;
 
1616
                                }
 
1617
 
 
1618
                                if(val && (event==PKEY))
 
1619
                                {
 
1620
                                        if(inset)inset = 0;
 
1621
                                        else inset = 1;
 
1622
                                }
 
1623
 
 
1624
                                if(val && (event==FKEY))
 
1625
                                {
 
1626
                                                int ct;
 
1627
                                                for(ct = 0; ct < ect; ct++){
 
1628
                                                        if(tagged[ct]->f2 & 32) 
 
1629
                                                                tagged[ct]->f2 &= ~32;
 
1630
                                                        else
 
1631
                                                                tagged[ct]->f2 |= 32;
 
1632
                                                }
 
1633
                                }
 
1634
 
 
1635
                                if(val && (event == MIDDLEMOUSE))
 
1636
                                {
 
1637
                                        cut = 2;
 
1638
                                        searching=0;
 
1639
                                }
 
1640
                                else if(val && (event==LEFTMOUSE || event==RETKEY))
 
1641
                                {
 
1642
                                        searching=0;
 
1643
                                }
 
1644
 
 
1645
                                if(val && (event==ESCKEY || event==RIGHTMOUSE ))
 
1646
                                {
 
1647
                                        searching=0;
 
1648
                                        cut = 0;
 
1649
                                }
 
1650
                                
 
1651
                        }                       
 
1652
                        
 
1653
                        /* window coords, no clip with vertices f2 flags set (not used) */
 
1654
                        calc_meshverts_ext_f2();
 
1655
 
 
1656
 
 
1657
                        /* Determine the % on wich the loop should be cut */
 
1658
                        getmouseco_areawin(mval);                       
 
1659
                        v1[0]=(float)mval[0];
 
1660
                        v1[1]=(float)mval[1];
 
1661
                        
 
1662
                        v2[0]=(float)start->v1->xs;
 
1663
                        v2[1]=(float)start->v1->ys;
 
1664
                        
 
1665
                        v3[0]=(float)start->v2->xs;
 
1666
                        v3[1]=(float)start->v2->ys;
 
1667
                        
 
1668
                        rc[0]= v3[0]-v2[0];
 
1669
                        rc[1]= v3[1]-v2[1];
 
1670
                        len= rc[0]*rc[0]+ rc[1]*rc[1];
 
1671
                                
 
1672
                        labda= ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
 
1673
 
 
1674
 
 
1675
                        if(labda<=0.0) labda=0.0;
 
1676
                        else if(labda>=1.0)labda=1.0;
 
1677
                                                
 
1678
                        percentcut=labda;               
 
1679
                        
 
1680
                        if(start->f2 & 32)
 
1681
                                percentcut = 1.0-percentcut;
 
1682
 
 
1683
                if(cut == 2){
 
1684
                        percentcut = 0.5;
 
1685
                }
 
1686
 
 
1687
                if (G.qual & LR_SHIFTKEY){
 
1688
 
 
1689
                        percentcut = (int)(percentcut*100.0)/100.0;     
 
1690
                }
 
1691
                else if (G.qual & LR_CTRLKEY)
 
1692
                        percentcut = (int)(percentcut*10.0)/10.0;               
 
1693
        
 
1694
                outcut = (percentcut*100.0);
 
1695
 
 
1696
                /* Build the Header Line */ 
 
1697
 
 
1698
                if(inset)
 
1699
                        sprintf(mesg,"Cut: %0.2f%% ",slen*percentcut);
 
1700
                else
 
1701
                        sprintf(mesg,"Cut: %0.2f%% ",outcut);
 
1702
                
 
1703
 
 
1704
                if(smooth)
 
1705
                        sprintf(mesg,"%s| (f)lip side | (s)mooth on  |",mesg);
 
1706
                else
 
1707
                        sprintf(mesg,"%s| (f)lip side | (s)mooth off |",mesg);
 
1708
 
 
1709
                if(inset)
 
1710
                        sprintf(mesg,"%s (p)roportional on ",mesg);
 
1711
                else
 
1712
                        sprintf(mesg,"%s (p)roportional off",mesg);
 
1713
                
 
1714
                headerprint(mesg);
 
1715
 
 
1716
                screen_swapbuffers();           
 
1717
        }                       
 
1718
        
 
1719
        if(cut){
 
1720
                /* Now that we have selected a cut %, mark the edges for cutting. */
 
1721
                if(!inset){
 
1722
 
 
1723
                        for(eed = em->edges.first; eed; eed=eed->next){
 
1724
                                if(percentcut == 1.0)
 
1725
                                        percentcut = 0.9999;
 
1726
                                else if(percentcut == 0.0)
 
1727
                                        percentcut = 0.0001;
 
1728
                                if(eed->f2 & 8){
 
1729
                                        if(eed->f2 & 32)/* Need to offset by a const. (0.5/32768) for consistant roundoff */
 
1730
                                                eed->f1 = 32768*(1.0-percentcut - 0.0000153);
 
1731
                                        else
 
1732
                                                eed->f1 = 32768*(percentcut + 0.0000153);
 
1733
                                }
 
1734
                        }
 
1735
                }
 
1736
        /*-------------------------------------*/
 
1737
 
 
1738
                        if(smooth)
 
1739
                                subdivideflag(8, 0, B_KNIFE | B_PERCENTSUBD | B_SMOOTH); /* B_KNIFE tells subdivide that edgeflags are already set */
 
1740
                        else
 
1741
                                subdivideflag(8, 0, B_KNIFE | B_PERCENTSUBD); /* B_KNIFE tells subdivide that edgeflags are already set */
 
1742
                        
 
1743
                        for(eed = em->edges.first; eed; eed=eed->next){                                                 
 
1744
                                if(eed->v1->f & 16) eed->v1->f |= SELECT; //
 
1745
                                else eed->v1->f &= ~SELECT;
 
1746
                                
 
1747
                                if(eed->v2->f & 16) eed->v2->f |= SELECT;
 
1748
                                else eed->v2->f &= ~SELECT;
 
1749
                                
 
1750
                                /* proper edge select state, needed because subdivide still doesnt do it OK */
 
1751
                                if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
 
1752
                                else eed->f &= ~SELECT;
 
1753
                        }                       
 
1754
                }
 
1755
        }
 
1756
        /*----------END Cut Loop-----------------------------*/
 
1757
 
 
1758
        
 
1759
 
 
1760
        /* Clear flags */               
 
1761
        for(eed = em->edges.first; eed; eed=eed->next){ 
 
1762
                eed->f2 &= ~(2|4|8|32|64);
 
1763
                eed->v1->f &= ~(2|16); // xxx
 
1764
                eed->v2->f &= ~(2|16);          
 
1765
        }
 
1766
        
 
1767
        for(efa= em->faces.first; efa; efa=efa->next){
 
1768
                efa->f1 &= ~(4|8);
 
1769
 
 
1770
                /* proper face select state, needed because subdivide still doesnt do it OK */
 
1771
                if( faceselectedAND(efa, SELECT) ) efa->f |= SELECT;
 
1772
                else efa->f &= ~SELECT;
 
1773
        }
 
1774
        
 
1775
        // flushes vertex -> edge -> face selection
 
1776
        EM_select_flush();
 
1777
        
 
1778
        countall();
 
1779
 
 
1780
        if(tagged)
 
1781
                MEM_freeN(tagged);
 
1782
        if(taggedsrch)
 
1783
                MEM_freeN(taggedsrch);
 
1784
        if(percentfacesloop)
 
1785
                MEM_freeN(percentfacesloop);
 
1786
        
 
1787
        /* send event to redraw this window, does header too */ 
 
1788
        SetBlenderCursor(SYSCURSOR);
 
1789
        addqueue(curarea->win, REDRAW, 1); 
 
1790
 
 
1791
        /* should have check for cancelled (ton) */
 
1792
        if(mode==LOOP_CUT) BIF_undo_push("Face Loop Subdivide");
 
1793
        else if(mode==LOOP_SELECT) BIF_undo_push("Select Face Loop");   
 
1794
 
 
1795
}
 
1796
 
 
1797
/* ****************************** END LOOPOPERATIONS ********************** */
 
1798
 
 
1799
void LoopMenu(){ /* Called by KKey */
 
1800
 
 
1801
        short ret;
 
1802
        
 
1803
        ret=pupmenu("Loop/Cut Menu %t|Face Loop Select %x1|Face Loop Cut %x2|"
 
1804
                                "Knife (Exact) %x3|Knife (Midpoints)%x4|");
 
1805
                                
 
1806
        switch (ret){
 
1807
                case 1:
 
1808
                        loopoperations(LOOP_SELECT);
 
1809
                        break;
 
1810
                case 2:
 
1811
                        loopoperations(LOOP_CUT);
 
1812
                        break;
 
1813
                case 3: 
 
1814
                        KnifeSubdivide(KNIFE_EXACT);
 
1815
                        break;
 
1816
                case 4:
 
1817
                        KnifeSubdivide(KNIFE_MIDPOINT);
 
1818
        }
 
1819
 
 
1820
}
 
1821