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

« back to all changes in this revision

Viewing changes to source/blender/src/editmesh_mods.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_mods.c, UI level access, no geometry changes 
 
36
 
 
37
*/
 
38
 
 
39
#include <stdlib.h>
 
40
#include <string.h>
 
41
#include <math.h>
 
42
 
 
43
#ifdef HAVE_CONFIG_H
 
44
#include <config.h>
 
45
#endif
 
46
 
 
47
#include "MEM_guardedalloc.h"
 
48
 
 
49
#include "MTC_matrixops.h"
 
50
 
 
51
#include "DNA_mesh_types.h"
 
52
#include "DNA_material_types.h"
 
53
#include "DNA_meshdata_types.h"
 
54
#include "DNA_object_types.h"
 
55
#include "DNA_texture_types.h"
 
56
#include "DNA_scene_types.h"
 
57
#include "DNA_screen_types.h"
 
58
#include "DNA_view3d_types.h"
 
59
 
 
60
#include "BLI_blenlib.h"
 
61
#include "BLI_arithb.h"
 
62
#include "BLI_editVert.h"
 
63
#include "BLI_rand.h"
 
64
 
 
65
#include "BKE_displist.h"
 
66
#include "BKE_DerivedMesh.h"
 
67
#include "BKE_global.h"
 
68
#include "BKE_mesh.h"
 
69
#include "BKE_material.h"
 
70
#include "BKE_texture.h"
 
71
#include "BKE_utildefines.h"
 
72
 
 
73
#include "BIF_editmesh.h"
 
74
#include "BIF_resources.h"
 
75
#include "BIF_gl.h"
 
76
#include "BIF_glutil.h"
 
77
#include "BIF_graphics.h"
 
78
#include "BIF_interface.h"
 
79
#include "BIF_mywindow.h"
 
80
#include "BIF_resources.h"
 
81
#include "BIF_screen.h"
 
82
#include "BIF_space.h"
 
83
#include "BIF_toolbox.h"
 
84
 
 
85
#include "BDR_drawobject.h"
 
86
#include "BDR_editobject.h"
 
87
 
 
88
#include "BSE_drawview.h"
 
89
#include "BSE_edit.h"
 
90
#include "BSE_view.h"
 
91
 
 
92
#include "IMB_imbuf.h"
 
93
 
 
94
#include "mydevice.h"
 
95
#include "blendef.h"
 
96
#include "render.h"  // externtex
 
97
 
 
98
#include "editmesh.h"
 
99
 
 
100
 
 
101
/* ****************************** SELECTION ROUTINES **************** */
 
102
 
 
103
int em_solidoffs=0, em_wireoffs=0, em_vertoffs; // set in drawobject.c ... for colorindices
 
104
 
 
105
static void check_backbuf(void)
 
106
{
 
107
        if(G.vd->flag & V3D_NEEDBACKBUFDRAW) {
 
108
                backdrawview3d(0);
 
109
        }
 
110
}
 
111
 
 
112
/* samples a single pixel (copied from vpaint) */
 
113
static unsigned int sample_backbuf(int x, int y)
 
114
{
 
115
        unsigned int col;
 
116
        
 
117
        if(x>=curarea->winx || y>=curarea->winy) return 0;
 
118
        x+= curarea->winrct.xmin;
 
119
        y+= curarea->winrct.ymin;
 
120
        
 
121
        check_backbuf(); // actually not needed for apple
 
122
 
 
123
#ifdef __APPLE__
 
124
        glReadBuffer(GL_AUX0);
 
125
#endif
 
126
        glReadPixels(x,  y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,  &col);
 
127
        glReadBuffer(GL_BACK);  
 
128
        
 
129
        if(G.order==B_ENDIAN) SWITCH_INT(col);
 
130
        
 
131
        return framebuffer_to_index(col);
 
132
}
 
133
 
 
134
/* reads full rect, converts indices */
 
135
static unsigned int *read_backbuf(short xmin, short ymin, short xmax, short ymax)
 
136
{
 
137
        unsigned int *dr, *buf;
 
138
        int a;
 
139
        short xminc, yminc, xmaxc, ymaxc;
 
140
        
 
141
        /* clip */
 
142
        if(xmin<0) xminc= 0; else xminc= xmin;
 
143
        if(xmax>=curarea->winx) xmaxc= curarea->winx-1; else xmaxc= xmax;
 
144
        if(xminc > xmaxc) return NULL;
 
145
 
 
146
        if(ymin<0) yminc= 0; else yminc= ymin;
 
147
        if(ymax>=curarea->winy) ymaxc= curarea->winy-1; else ymaxc= ymax;
 
148
        if(yminc > ymaxc) return NULL;
 
149
        
 
150
        buf= MEM_mallocN( (xmaxc-xminc+1)*(ymaxc-yminc+1)*sizeof(int), "sample rect");
 
151
 
 
152
        check_backbuf(); // actually not needed for apple
 
153
        
 
154
#ifdef __APPLE__
 
155
        glReadBuffer(GL_AUX0);
 
156
#endif
 
157
        glReadPixels(curarea->winrct.xmin+xminc, curarea->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, buf);
 
158
        glReadBuffer(GL_BACK);  
 
159
 
 
160
        if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr((xmaxc-xminc+1)*(ymaxc-yminc+1), buf);
 
161
 
 
162
        a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
 
163
        dr= buf;
 
164
        while(a--) {
 
165
                if(*dr) *dr= framebuffer_to_index(*dr);
 
166
                dr++;
 
167
        }
 
168
        
 
169
        /* put clipped result back, if needed */
 
170
        if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) return buf;
 
171
        else {
 
172
                unsigned int *buf1= MEM_callocN( (xmax-xmin+1)*(ymax-ymin+1)*sizeof(int), "sample rect2");
 
173
                unsigned int *rd;
 
174
                short xs, ys;
 
175
 
 
176
                rd= buf;
 
177
                dr= buf1;
 
178
                
 
179
                for(ys= ymin; ys<=ymax; ys++) {
 
180
                        for(xs= xmin; xs<=xmax; xs++, dr++) {
 
181
                                if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
 
182
                                        *dr= *rd;
 
183
                                        rd++;
 
184
                                }
 
185
                        }
 
186
                }
 
187
                MEM_freeN(buf);
 
188
                return buf1;
 
189
        }
 
190
        
 
191
        return buf;
 
192
}
 
193
 
 
194
 
 
195
/* smart function to sample a rect spiralling outside, nice for backbuf selection */
 
196
static unsigned int sample_backbuf_rect(unsigned int *buf, int size, int min, int max, short *dist)
 
197
{
 
198
        unsigned int *bufmin, *bufmax;
 
199
        int a, b, rc, nr, amount, dirvec[4][2];
 
200
        short distance=0;
 
201
        
 
202
        amount= (size-1)/2;
 
203
        rc= 0;
 
204
        
 
205
        dirvec[0][0]= 1; dirvec[0][1]= 0;
 
206
        dirvec[1][0]= 0; dirvec[1][1]= -size;
 
207
        dirvec[2][0]= -1; dirvec[2][1]= 0;
 
208
        dirvec[3][0]= 0; dirvec[3][1]= size;
 
209
        
 
210
        bufmin= buf;
 
211
        bufmax= buf+ size*size;
 
212
        buf+= amount*size+ amount;
 
213
        
 
214
        for(nr=1; nr<=size; nr++) {
 
215
                
 
216
                for(a=0; a<2; a++) {
 
217
                        for(b=0; b<nr; b++, distance++) {
 
218
                                
 
219
                                if(*buf && *buf>=min && *buf<max ) {
 
220
                                        *dist= (short) sqrt( (float)distance );
 
221
                                        return *buf - min+1;    // messy yah, but indices start at 1
 
222
                                }
 
223
                                
 
224
                                buf+= (dirvec[rc][0]+dirvec[rc][1]);
 
225
                                
 
226
                                if(buf<bufmin || buf>=bufmax) {
 
227
                                        return 0;
 
228
                                }
 
229
                        }
 
230
                        rc++;
 
231
                        rc &= 3;
 
232
                }
 
233
        }
 
234
        return 0;
 
235
}
 
236
 
 
237
/* facilities for border select and circle select */
 
238
static char *selbuf= NULL;
 
239
 
 
240
/* opengl doesn't support concave... */
 
241
static void draw_triangulated(short mcords[][2], short tot)
 
242
{
 
243
        ListBase lb={NULL, NULL};
 
244
        DispList *dl;
 
245
        float *fp;
 
246
        int a;
 
247
        
 
248
        /* make displist */
 
249
        dl= MEM_callocN(sizeof(DispList), "poly disp");
 
250
        dl->type= DL_POLY;
 
251
        dl->parts= 1;
 
252
        dl->nr= tot;
 
253
        dl->verts= fp=  MEM_callocN(tot*3*sizeof(float), "poly verts");
 
254
        BLI_addtail(&lb, dl);
 
255
        
 
256
        for(a=0; a<tot; a++, fp+=3) {
 
257
                fp[0]= (float)mcords[a][0];
 
258
                fp[1]= (float)mcords[a][1];
 
259
        }
 
260
        
 
261
        /* do the fill */
 
262
        filldisplist(&lb, &lb);
 
263
 
 
264
        /* do the draw */
 
265
        dl= lb.first;   // filldisplist adds in head of list
 
266
        if(dl->type==DL_INDEX3) {
 
267
                int *index;
 
268
                
 
269
                a= dl->parts;
 
270
                fp= dl->verts;
 
271
                index= dl->index;
 
272
                glBegin(GL_TRIANGLES);
 
273
                while(a--) {
 
274
                        glVertex3fv(fp+3*index[0]);
 
275
                        glVertex3fv(fp+3*index[1]);
 
276
                        glVertex3fv(fp+3*index[2]);
 
277
                        index+= 3;
 
278
                }
 
279
                glEnd();
 
280
        }
 
281
        
 
282
        freedisplist(&lb);
 
283
}
 
284
 
 
285
 
 
286
/* reads rect, and builds selection array for quick lookup */
 
287
/* returns if all is OK */
 
288
int EM_init_backbuf_border(short xmin, short ymin, short xmax, short ymax)
 
289
{
 
290
        unsigned int *buf, *dr;
 
291
        int a;
 
292
        
 
293
        if(G.obedit==NULL || G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
 
294
        if(em_vertoffs==0) return 0;
 
295
        
 
296
        dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
 
297
        if(buf==NULL) return 0;
 
298
        
 
299
        /* build selection lookup */
 
300
        selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
 
301
        
 
302
        a= (xmax-xmin+1)*(ymax-ymin+1);
 
303
        while(a--) {
 
304
                if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
 
305
                dr++;
 
306
        }
 
307
        MEM_freeN(buf);
 
308
        return 1;
 
309
}
 
310
 
 
311
int EM_check_backbuf_border(int index)
 
312
{
 
313
        if(selbuf==NULL) return 1;
 
314
        if(index>0 && index<=em_vertoffs)
 
315
                return selbuf[index];
 
316
        return 0;
 
317
}
 
318
 
 
319
void EM_free_backbuf_border(void)
 
320
{
 
321
        if(selbuf) MEM_freeN(selbuf);
 
322
        selbuf= NULL;
 
323
}
 
324
 
 
325
/* mcords is a polygon mask
 
326
   - grab backbuffer,
 
327
   - draw with black in backbuffer, 
 
328
   - grab again and compare
 
329
   returns 'OK' 
 
330
*/
 
331
int EM_mask_init_backbuf_border(short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
 
332
{
 
333
        unsigned int *buf, *bufmask, *dr, *drm;
 
334
        int a;
 
335
        
 
336
        /* method in use for face selecting too */
 
337
        if(G.obedit==NULL) {
 
338
                if(G.f & G_FACESELECT);
 
339
                else return 0;
 
340
        }
 
341
        else if(G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
 
342
 
 
343
        if(em_vertoffs==0) return 0;
 
344
        
 
345
        dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
 
346
        if(buf==NULL) return 0;
 
347
 
 
348
        /* draw the mask */
 
349
#ifdef __APPLE__
 
350
        glDrawBuffer(GL_AUX0);
 
351
#endif
 
352
        glDisable(GL_DEPTH_TEST);
 
353
        
 
354
        persp(PERSP_WIN);
 
355
        glColor3ub(0, 0, 0);
 
356
        
 
357
        /* yah, opengl doesn't do concave... tsk! */
 
358
        draw_triangulated(mcords, tot); 
 
359
        
 
360
        glBegin(GL_LINE_LOOP);  // for zero sized masks, lines
 
361
        for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
 
362
        glEnd();
 
363
        
 
364
        persp(PERSP_VIEW);
 
365
        glFinish();     // to be sure readpixels sees mask
 
366
        
 
367
        glDrawBuffer(GL_BACK);
 
368
        
 
369
        /* grab mask */
 
370
        drm= bufmask= read_backbuf(xmin, ymin, xmax, ymax);
 
371
        if(bufmask==NULL) return 0; // only when mem alloc fails, go crash somewhere else!
 
372
        
 
373
        /* build selection lookup */
 
374
        selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
 
375
        
 
376
        a= (xmax-xmin+1)*(ymax-ymin+1);
 
377
        while(a--) {
 
378
                if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1;
 
379
                dr++; drm++;
 
380
        }
 
381
        MEM_freeN(buf);
 
382
        MEM_freeN(bufmask);
 
383
        return 1;
 
384
        
 
385
}
 
386
 
 
387
/* circle shaped sample area */
 
388
int EM_init_backbuf_circle(short xs, short ys, short rads)
 
389
{
 
390
        unsigned int *buf, *dr;
 
391
        short xmin, ymin, xmax, ymax, xc, yc;
 
392
        int radsq;
 
393
        
 
394
        if(G.obedit==NULL || G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
 
395
        if(em_vertoffs==0) return 0;
 
396
        
 
397
        xmin= xs-rads; xmax= xs+rads;
 
398
        ymin= ys-rads; ymax= ys+rads;
 
399
        dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
 
400
        if(buf==NULL) return 0;
 
401
        
 
402
        /* build selection lookup */
 
403
        selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
 
404
        radsq= rads*rads;
 
405
        for(yc= -rads; yc<=rads; yc++) {
 
406
                for(xc= -rads; xc<=rads; xc++, dr++) {
 
407
                        if(xc*xc + yc*yc < radsq) {
 
408
                                if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
 
409
                        }
 
410
                }
 
411
        }
 
412
 
 
413
        MEM_freeN(buf);
 
414
        return 1;
 
415
        
 
416
}
 
417
 
 
418
 
 
419
static EditVert *findnearestvert_f(short *dist, short sel)
 
420
{
 
421
        static EditVert *acto= NULL;
 
422
        EditMesh *em = G.editMesh;
 
423
        /* if sel==1 the vertices with flag==1 get a disadvantage */
 
424
        EditVert *eve,*act=NULL;
 
425
        short temp, mval[2];
 
426
 
 
427
        if(em->verts.first==NULL) return NULL;
 
428
 
 
429
        /* do projection */
 
430
        calc_meshverts_ext();   /* drawobject.c */
 
431
        
 
432
        /* we count from acto->next to last, and from first to acto */
 
433
        /* does acto exist? */
 
434
        eve= em->verts.first;
 
435
        while(eve) {
 
436
                if(eve==acto) break;
 
437
                eve= eve->next;
 
438
        }
 
439
        if(eve==NULL) acto= em->verts.first;
 
440
 
 
441
        /* is there an indicated vertex? part 1 */
 
442
        getmouseco_areawin(mval);
 
443
        eve= acto->next;
 
444
        while(eve) {
 
445
                if(eve->h==0 && eve->xs!=3200) {
 
446
                        temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
 
447
                        if( (eve->f & 1)==sel ) temp+=5;
 
448
                        if(temp< *dist) {
 
449
                                act= eve;
 
450
                                *dist= temp;
 
451
                                if(*dist<4) break;
 
452
                        }
 
453
                }
 
454
                eve= eve->next;
 
455
        }
 
456
        /* is there an indicated vertex? part 2 */
 
457
        if(*dist>3) {
 
458
                eve= em->verts.first;
 
459
                while(eve) {
 
460
                        if(eve->h==0 && eve->xs!=3200) {
 
461
                                temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
 
462
                                if( (eve->f & 1)==sel ) temp+=5;
 
463
                                if(temp< *dist) {
 
464
                                        act= eve;
 
465
                                        if(temp<4) break;
 
466
                                        *dist= temp;
 
467
                                }
 
468
                                if(eve== acto) break;
 
469
                        }
 
470
                        eve= eve->next;
 
471
                }
 
472
        }
 
473
 
 
474
        acto= act;
 
475
        return act;
 
476
}
 
477
 
 
478
/* backbuffer version */
 
479
static EditVert *findnearestvert(short *dist, short sel)
 
480
{
 
481
        if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
 
482
                EditVert *eve=NULL;
 
483
                unsigned int *buf;
 
484
                int a=1, index;
 
485
                short mval[2], distance=255;
 
486
                
 
487
                getmouseco_areawin(mval);
 
488
                
 
489
                // sample colorcode 
 
490
                buf= read_backbuf(mval[0]-25, mval[1]-25, mval[0]+24, mval[1]+24);
 
491
                if(buf) {
 
492
                        index= sample_backbuf_rect(buf, 50, em_wireoffs, 0xFFFFFF, &distance); // globals, set in drawobject.c
 
493
                        MEM_freeN(buf);
 
494
                        if(distance < *dist) {
 
495
                                if(index>0) for(eve= G.editMesh->verts.first; eve; eve= eve->next, a++) if(index==a) break;
 
496
                                if(eve) *dist= distance;
 
497
                        }
 
498
                }
 
499
                return eve;
 
500
        }
 
501
        else return findnearestvert_f(dist, sel);
 
502
}
 
503
 
 
504
/* helper for findnearest edge */
 
505
static float dist_mval_edge(short *mval, EditEdge *eed)
 
506
{
 
507
        float v1[2], v2[2], mval2[2];
 
508
 
 
509
        mval2[0] = (float)mval[0];
 
510
        mval2[1] = (float)mval[1];
 
511
        
 
512
        v1[0] = eed->v1->xs;
 
513
        v1[1] = eed->v1->ys;
 
514
        v2[0] = eed->v2->xs;
 
515
        v2[1] = eed->v2->ys;
 
516
        
 
517
        return PdistVL2Dfl(mval2, v1, v2);
 
518
}
 
519
 
 
520
static EditEdge *findnearestedge_f(short *dist)
 
521
{
 
522
        EditMesh *em = G.editMesh;
 
523
        EditEdge *closest, *eed;
 
524
        EditVert *eve;
 
525
        short mval[2], distance;
 
526
        
 
527
        if(em->edges.first==NULL) return NULL;
 
528
        else eed= em->edges.first;      
 
529
        
 
530
        calc_meshverts_ext_f2();        /* sets/clears (eve->f & 2) for vertices that aren't visible */
 
531
 
 
532
        getmouseco_areawin(mval);
 
533
        closest=NULL;
 
534
        
 
535
        /*compare the distance to the rest of the edges and find the closest one*/
 
536
        eed=em->edges.first;
 
537
        while(eed) {
 
538
                /* Are both vertices of the edge ofscreen or either of them hidden? then don't select the edge*/
 
539
                if( !((eed->v1->f & 2) && (eed->v2->f & 2)) && eed->h==0){
 
540
                        
 
541
                        distance= dist_mval_edge(mval, eed);
 
542
                        if(eed->f & SELECT) distance+=5;
 
543
                        if(distance < *dist) {
 
544
                                *dist= distance;
 
545
                                closest= eed;
 
546
                        }
 
547
                }
 
548
                eed= eed->next;
 
549
        }
 
550
        
 
551
        /* reset flags */       
 
552
        for(eve=em->verts.first; eve; eve=eve->next){
 
553
                eve->f &= ~2;
 
554
        }
 
555
        
 
556
        return closest;
 
557
}
 
558
 
 
559
/* backbuffer version */
 
560
EditEdge *findnearestedge(short *dist)
 
561
{
 
562
        if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
 
563
                EditEdge *eed=NULL;
 
564
                unsigned int *buf;
 
565
                int a=1, index;
 
566
                short mval[2], distance=255;
 
567
                
 
568
                getmouseco_areawin(mval);
 
569
                // sample colorcode 
 
570
 
 
571
                buf= read_backbuf(mval[0]-25, mval[1]-25, mval[0]+24, mval[1]+24);
 
572
                if(buf) {
 
573
                        index= sample_backbuf_rect(buf, 50, em_solidoffs, em_wireoffs, &distance); // global, set in drawobject.c
 
574
                        MEM_freeN(buf);
 
575
                        if(distance < *dist) {
 
576
                                if(index>0 && index<=em_wireoffs-em_solidoffs) {
 
577
                                        for(eed= G.editMesh->edges.first; eed; eed= eed->next, a++) 
 
578
                                                if(index==a) break;
 
579
                                }
 
580
                                if(eed) *dist= distance;
 
581
                        }
 
582
                }
 
583
                
 
584
                return eed;
 
585
        }
 
586
        else return findnearestedge_f(dist);
 
587
}
 
588
 
 
589
 
 
590
static EditFace *findnearestface_f(short *dist)
 
591
{
 
592
        static EditFace *acto= NULL;
 
593
        EditMesh *em = G.editMesh;
 
594
        /* if selected the faces with flag==1 get a disadvantage */
 
595
        EditFace *efa, *act=NULL;
 
596
        short temp, mval[2];
 
597
 
 
598
        if(em->faces.first==NULL) return NULL;
 
599
 
 
600
        /* do projection */
 
601
        calc_mesh_facedots_ext();
 
602
        
 
603
        /* we count from acto->next to last, and from first to acto */
 
604
        /* does acto exist? */
 
605
        efa= em->faces.first;
 
606
        while(efa) {
 
607
                if(efa==acto) break;
 
608
                efa= efa->next;
 
609
        }
 
610
        if(efa==NULL) acto= em->faces.first;
 
611
 
 
612
        /* is there an indicated face? part 1 */
 
613
        getmouseco_areawin(mval);
 
614
        efa= acto->next;
 
615
        while(efa) {
 
616
                if(efa->h==0 && efa->fgonf!=EM_FGON) {
 
617
                        temp= abs(mval[0]- efa->xs)+ abs(mval[1]- efa->ys);
 
618
                        if(temp< *dist) {
 
619
                                act= efa;
 
620
                                *dist= temp;
 
621
                        }
 
622
                }
 
623
                efa= efa->next;
 
624
        }
 
625
        /* is there an indicated face? part 2 */
 
626
        if(*dist>3) {
 
627
                efa= em->faces.first;
 
628
                while(efa) {
 
629
                        if(efa->h==0 && efa->fgonf!=EM_FGON) {
 
630
                                temp= abs(mval[0]- efa->xs)+ abs(mval[1]- efa->ys);
 
631
                                if(temp< *dist) {
 
632
                                        act= efa;
 
633
                                        *dist= temp;
 
634
                                }
 
635
                                if(efa== acto) break;
 
636
                        }
 
637
                        efa= efa->next;
 
638
                }
 
639
        }
 
640
 
 
641
        acto= act;
 
642
        return act;
 
643
}
 
644
 
 
645
static EditFace *findnearestface(short *dist)
 
646
{
 
647
        if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
 
648
                EditFace *efa=NULL;
 
649
                int a=1, index;
 
650
                short mval[2], distance;
 
651
 
 
652
                calc_mesh_facedots_ext();       // shouldnt be needed each click
 
653
                getmouseco_areawin(mval);
 
654
 
 
655
                // sample colorcode 
 
656
                index= sample_backbuf(mval[0], mval[1]);
 
657
                
 
658
                if(index && index<=em_solidoffs) {
 
659
                        for(efa= G.editMesh->faces.first; efa; efa= efa->next, a++) if(index==a) break;
 
660
                        if(efa) {
 
661
                                distance= abs(mval[0]- efa->xs)+ abs(mval[1]- efa->ys);
 
662
 
 
663
                                if(G.scene->selectmode == SCE_SELECT_FACE || distance<*dist) {  // only faces, no dist check
 
664
                                        *dist= distance;
 
665
                                        return efa;
 
666
                                }
 
667
                        }
 
668
                }
 
669
                
 
670
                return NULL;
 
671
        }
 
672
        else return findnearestface_f(dist);
 
673
}
 
674
 
 
675
/* for interactivity, frontbuffer draw in current window */
 
676
static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
 
677
{
 
678
        int dmNeedsFree;
 
679
        DerivedMesh *dm = mesh_get_cage_derived(G.obedit, &dmNeedsFree);
 
680
 
 
681
        glDrawBuffer(GL_FRONT);
 
682
 
 
683
        persp(PERSP_VIEW);
 
684
        glPushMatrix();
 
685
        mymultmatrix(G.obedit->obmat);
 
686
        
 
687
        /* face selected */
 
688
        if(efa) {
 
689
                if(G.scene->selectmode & SCE_SELECT_VERTEX) {
 
690
                        glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
 
691
                        
 
692
                        if(efa->f & SELECT) BIF_ThemeColor(TH_VERTEX_SELECT);
 
693
                        else BIF_ThemeColor(TH_VERTEX);
 
694
                        
 
695
                        bglBegin(GL_POINTS);
 
696
                        bglVertex3fv(efa->v1->co);
 
697
                        bglVertex3fv(efa->v2->co);
 
698
                        bglVertex3fv(efa->v3->co);
 
699
                        if(efa->v4) bglVertex3fv(efa->v4->co);
 
700
                        bglEnd();
 
701
                }
 
702
 
 
703
                if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
 
704
                        if(efa->fgonf==0) {
 
705
                                BIF_ThemeColor((efa->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
 
706
        
 
707
                                dm->drawMappedEdgeEM(dm, efa->e1);
 
708
                                dm->drawMappedEdgeEM(dm, efa->e2);
 
709
                                dm->drawMappedEdgeEM(dm, efa->e3);
 
710
                                if (efa->e4) {
 
711
                                        dm->drawMappedEdgeEM(dm, efa->e4);
 
712
                                }
 
713
                        }
 
714
                }
 
715
                
 
716
                if(G.scene->selectmode & SCE_SELECT_FACE) {
 
717
                        if(efa->fgonf==0) {
 
718
                                glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));
 
719
                                BIF_ThemeColor((efa->f & SELECT)?TH_FACE_DOT:TH_WIRE);
 
720
 
 
721
                                bglBegin(GL_POINTS);
 
722
                                bglVertex3fv(efa->cent);
 
723
                                bglEnd();
 
724
                        }
 
725
                }
 
726
        }
 
727
        /* edge selected */
 
728
        if(eed) {
 
729
                if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
 
730
                        BIF_ThemeColor((eed->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
 
731
 
 
732
                        dm->drawMappedEdgeEM(dm, eed);
 
733
                }
 
734
                if(G.scene->selectmode & SCE_SELECT_VERTEX) {
 
735
                        float co[3];
 
736
                        glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
 
737
                        
 
738
                        BIF_ThemeColor((eed->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
 
739
                        
 
740
                        bglBegin(GL_POINTS);
 
741
                        dm->getMappedVertCoEM(dm, eed->v1, co);
 
742
                        bglVertex3fv(co);
 
743
 
 
744
                        dm->getMappedVertCoEM(dm, eed->v2, co);
 
745
                        bglVertex3fv(co);
 
746
                        bglEnd();
 
747
                }
 
748
        }
 
749
        if(eve) {
 
750
                if(G.scene->selectmode & SCE_SELECT_VERTEX) {
 
751
                        float co[3];
 
752
                        glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
 
753
                        
 
754
                        BIF_ThemeColor((eve->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
 
755
                        
 
756
                        bglBegin(GL_POINTS);
 
757
                        dm->getMappedVertCoEM(dm, eve, co);
 
758
                        bglVertex3fv(co);
 
759
                        bglEnd();
 
760
                }
 
761
        }
 
762
 
 
763
        glPointSize(1.0);
 
764
        glPopMatrix();
 
765
 
 
766
        glFlush();
 
767
        glDrawBuffer(GL_BACK);
 
768
 
 
769
        /* signal that frontbuf differs from back */
 
770
        curarea->win_swap= WIN_FRONT_OK;
 
771
 
 
772
        if (dmNeedsFree) {
 
773
                dm->release(dm);
 
774
        }
 
775
}
 
776
 
 
777
 
 
778
/* best distance based on screen coords. 
 
779
   use g.scene->selectmode to define how to use 
 
780
   selected vertices and edges get disadvantage
 
781
   return 1 if found one
 
782
*/
 
783
static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa) 
 
784
{
 
785
        short dist= 75;
 
786
        
 
787
        *eve= NULL;
 
788
        *eed= NULL;
 
789
        *efa= NULL;
 
790
        
 
791
        if(G.scene->selectmode & SCE_SELECT_VERTEX)
 
792
                *eve= findnearestvert(&dist, SELECT);
 
793
        if(G.scene->selectmode & SCE_SELECT_FACE)
 
794
                *efa= findnearestface(&dist);
 
795
 
 
796
        dist-= 20;      // since edges select lines, we give dots advantage of 20 pix
 
797
        if(G.scene->selectmode & SCE_SELECT_EDGE)
 
798
                *eed= findnearestedge(&dist);
 
799
 
 
800
        /* return only one of 3 pointers, for frontbuffer redraws */
 
801
        if(*eed) {
 
802
                *efa= NULL; *eve= NULL;
 
803
        }
 
804
        else if(*efa) {
 
805
                *eve= NULL;
 
806
        }
 
807
        
 
808
        return (*eve || *eed || *efa);
 
809
}
 
810
 
 
811
/* ****************  LOOP SELECTS *************** */
 
812
 
 
813
/* selects quads in loop direction of indicated edge */
 
814
/* only flush over edges with valence <= 2 */
 
815
static void faceloop_select(EditEdge *startedge, int select)
 
816
{
 
817
        EditMesh *em = G.editMesh;
 
818
        EditEdge *eed;
 
819
        EditFace *efa;
 
820
        int looking= 1;
 
821
        
 
822
        /* in eed->f1 we put the valence (amount of faces in edge) */
 
823
        /* in eed->f2 we put tagged flag as correct loop */
 
824
        /* in efa->f1 we put tagged flag as correct to select */
 
825
 
 
826
        for(eed= em->edges.first; eed; eed= eed->next) {
 
827
                eed->f1= 0;
 
828
                eed->f2= 0;
 
829
        }
 
830
        for(efa= em->faces.first; efa; efa= efa->next) {
 
831
                efa->f1= 0;
 
832
                if(efa->h==0) {
 
833
                        efa->e1->f1++;
 
834
                        efa->e2->f1++;
 
835
                        efa->e3->f1++;
 
836
                        if(efa->e4) efa->e4->f1++;
 
837
                }
 
838
        }
 
839
        
 
840
        // tag startedge OK
 
841
        startedge->f2= 1;
 
842
        
 
843
        while(looking) {
 
844
                looking= 0;
 
845
                
 
846
                for(efa= em->faces.first; efa; efa= efa->next) {
 
847
                        if(efa->e4 && efa->f1==0) {     // not done quad
 
848
                                if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
 
849
 
 
850
                                        // if edge tagged, select opposing edge and mark face ok
 
851
                                        if(efa->e1->f2) {
 
852
                                                efa->e3->f2= 1;
 
853
                                                efa->f1= 1;
 
854
                                                looking= 1;
 
855
                                        }
 
856
                                        else if(efa->e2->f2) {
 
857
                                                efa->e4->f2= 1;
 
858
                                                efa->f1= 1;
 
859
                                                looking= 1;
 
860
                                        }
 
861
                                        if(efa->e3->f2) {
 
862
                                                efa->e1->f2= 1;
 
863
                                                efa->f1= 1;
 
864
                                                looking= 1;
 
865
                                        }
 
866
                                        if(efa->e4->f2) {
 
867
                                                efa->e2->f2= 1;
 
868
                                                efa->f1= 1;
 
869
                                                looking= 1;
 
870
                                        }
 
871
                                }
 
872
                        }
 
873
                }
 
874
        }
 
875
        
 
876
        /* (de)select the faces */
 
877
        for(efa= em->faces.first; efa; efa= efa->next) {
 
878
                if(efa->f1) EM_select_face(efa, select);
 
879
        }
 
880
}
 
881
 
 
882
 
 
883
/* helper for edgeloop_select, checks for eed->f2 tag in faces */
 
884
static int edge_not_in_tagged_face(EditEdge *eed)
 
885
{
 
886
        EditMesh *em = G.editMesh;
 
887
        EditFace *efa;
 
888
        
 
889
        for(efa= em->faces.first; efa; efa= efa->next) {
 
890
                if(efa->h==0) {
 
891
                        if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) {      // edge is in face
 
892
                                if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) {     // face is tagged
 
893
                                        return 0;
 
894
                                }
 
895
                        }
 
896
                }
 
897
        }
 
898
        return 1;
 
899
}
 
900
 
 
901
/* selects or deselects edges that:
 
902
- if edges has 2 faces:
 
903
        - has vertices with valence of 4
 
904
        - not shares face with previous edge
 
905
- if edge has 1 face:
 
906
        - has vertices with valence 4
 
907
        - not shares face with previous edge
 
908
        - but also only 1 face
 
909
- if edge no face:
 
910
        - has vertices with valence 2
 
911
*/
 
912
static void edgeloop_select(EditEdge *starteed, int select)
 
913
{
 
914
        EditMesh *em = G.editMesh;
 
915
        EditVert *eve;
 
916
        EditEdge *eed;
 
917
        EditFace *efa;
 
918
        int looking= 1;
 
919
        
 
920
        /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
 
921
        /* in eed->f2 and efa->f1 we put tagged flag as correct loop */
 
922
        for(eve= em->verts.first; eve; eve= eve->next) {
 
923
                eve->f1= 0;
 
924
                eve->f2= 0;
 
925
        }
 
926
        for(eed= em->edges.first; eed; eed= eed->next) {
 
927
                eed->f1= 0;
 
928
                eed->f2= 0;
 
929
                if((eed->h & 1)==0) {   // fgon edges add to valence too
 
930
                        eed->v1->f1++; eed->v2->f1++;
 
931
                }
 
932
        }
 
933
        for(efa= em->faces.first; efa; efa= efa->next) {
 
934
                efa->f1= 0;
 
935
                if(efa->h==0) {
 
936
                        efa->e1->f1++;
 
937
                        efa->e2->f1++;
 
938
                        efa->e3->f1++;
 
939
                        if(efa->e4) efa->e4->f1++;
 
940
                }
 
941
        }
 
942
        
 
943
        /* looped edges & vertices get tagged f2 */
 
944
        starteed->f2= 1;
 
945
        if(starteed->v1->f1<5) starteed->v1->f2= 1;
 
946
        if(starteed->v2->f1<5) starteed->v2->f2= 1;
 
947
        /* sorry, first edge isnt even ok */
 
948
        if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
 
949
        
 
950
        while(looking) {
 
951
                looking= 0;
 
952
                
 
953
                /* find correct valence edges which are not tagged yet, but connect to tagged one */
 
954
                for(eed= em->edges.first; eed; eed= eed->next) {
 
955
                        if(eed->h==0 && eed->f2==0) { // edge not hidden, not tagged
 
956
                                if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { // valence of vertex OK, and is tagged
 
957
                                        /* new edge is not allowed to be in face with tagged edge */
 
958
                                        if(edge_not_in_tagged_face(eed)) {
 
959
                                                if(eed->f1==starteed->f1) {     // same amount of faces
 
960
                                                        looking= 1;
 
961
                                                        eed->f2= 1;
 
962
                                                        if(eed->v2->f1<5) eed->v2->f2= 1;
 
963
                                                        if(eed->v1->f1<5) eed->v1->f2= 1;
 
964
                                                }
 
965
                                        }
 
966
                                }
 
967
                        }
 
968
                }
 
969
        }
 
970
        /* and we do the select */
 
971
        for(eed= em->edges.first; eed; eed= eed->next) {
 
972
                if(eed->f2) EM_select_edge(eed, select);
 
973
        }
 
974
}
 
975
 
 
976
/* ***************** MAIN MOUSE SELECTION ************** */
 
977
 
 
978
// just to have the functions nice together
 
979
static void mouse_mesh_loop(void)
 
980
{
 
981
        EditEdge *eed;
 
982
        short dist= 50;
 
983
        
 
984
        eed= findnearestedge(&dist);
 
985
        if(eed) {
 
986
                
 
987
                if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
 
988
                
 
989
                if((eed->f & SELECT)==0) EM_select_edge(eed, 1);
 
990
                else if(G.qual & LR_SHIFTKEY) EM_select_edge(eed, 0);
 
991
 
 
992
                if(G.scene->selectmode & SCE_SELECT_FACE) {
 
993
                        faceloop_select(eed, eed->f & SELECT);
 
994
                }
 
995
                else {
 
996
                        edgeloop_select(eed, eed->f & SELECT);
 
997
                }
 
998
 
 
999
                /* frontbuffer draw of last selected only */
 
1000
                unified_select_draw(NULL, eed, NULL);
 
1001
                
 
1002
                EM_selectmode_flush();
 
1003
                countall();
 
1004
                
 
1005
                allqueue(REDRAWVIEW3D, 0);
 
1006
        }
 
1007
}
 
1008
 
 
1009
 
 
1010
/* here actual select happens */
 
1011
void mouse_mesh(void)
 
1012
{
 
1013
        EditVert *eve;
 
1014
        EditEdge *eed;
 
1015
        EditFace *efa;
 
1016
        
 
1017
        if(G.qual & LR_ALTKEY) mouse_mesh_loop();
 
1018
        else if(unified_findnearest(&eve, &eed, &efa)) {
 
1019
                
 
1020
                if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
 
1021
                
 
1022
                if(efa) {
 
1023
                        
 
1024
                        if( (efa->f & SELECT)==0 ) {
 
1025
                                EM_select_face_fgon(efa, 1);
 
1026
                        }
 
1027
                        else if(G.qual & LR_SHIFTKEY) {
 
1028
                                EM_select_face_fgon(efa, 0);
 
1029
                        }
 
1030
                }
 
1031
                else if(eed) {
 
1032
                        if((eed->f & SELECT)==0) {
 
1033
                                EM_select_edge(eed, 1);
 
1034
                        }
 
1035
                        else if(G.qual & LR_SHIFTKEY) {
 
1036
                                EM_select_edge(eed, 0);
 
1037
                        }
 
1038
                }
 
1039
                else if(eve) {
 
1040
                        if((eve->f & SELECT)==0) eve->f |= SELECT;
 
1041
                        else if(G.qual & LR_SHIFTKEY) eve->f &= ~SELECT;
 
1042
                }
 
1043
                
 
1044
                /* frontbuffer draw of last selected only */
 
1045
                unified_select_draw(eve, eed, efa);
 
1046
        
 
1047
                EM_selectmode_flush();
 
1048
                countall();
 
1049
 
 
1050
                allqueue(REDRAWVIEW3D, 0);
 
1051
        }
 
1052
 
 
1053
        rightmouse_transform();
 
1054
}
 
1055
 
 
1056
 
 
1057
static void selectconnectedAll(void)
 
1058
{
 
1059
        EditMesh *em = G.editMesh;
 
1060
        EditVert *v1,*v2;
 
1061
        EditEdge *eed;
 
1062
        short done=1, toggle=0;
 
1063
 
 
1064
        if(em->edges.first==0) return;
 
1065
        
 
1066
        while(done==1) {
 
1067
                done= 0;
 
1068
                
 
1069
                toggle++;
 
1070
                if(toggle & 1) eed= em->edges.first;
 
1071
                else eed= em->edges.last;
 
1072
                
 
1073
                while(eed) {
 
1074
                        v1= eed->v1;
 
1075
                        v2= eed->v2;
 
1076
                        if(eed->h==0) {
 
1077
                                if(v1->f & SELECT) {
 
1078
                                        if( (v2->f & SELECT)==0 ) {
 
1079
                                                v2->f |= SELECT;
 
1080
                                                done= 1;
 
1081
                                        }
 
1082
                                }
 
1083
                                else if(v2->f & SELECT) {
 
1084
                                        if( (v1->f & SELECT)==0 ) {
 
1085
                                                v1->f |= SELECT;
 
1086
                                                done= 1;
 
1087
                                        }
 
1088
                                }
 
1089
                        }
 
1090
                        if(toggle & 1) eed= eed->next;
 
1091
                        else eed= eed->prev;
 
1092
                }
 
1093
        }
 
1094
 
 
1095
        /* now use vertex select flag to select rest */
 
1096
        EM_select_flush();
 
1097
        
 
1098
        countall();
 
1099
 
 
1100
        allqueue(REDRAWVIEW3D, 0);
 
1101
        BIF_undo_push("Select Connected (All)");
 
1102
}
 
1103
 
 
1104
void selectconnected_mesh(int qual)
 
1105
{
 
1106
        EditMesh *em = G.editMesh;
 
1107
        EditVert *eve, *v1, *v2;
 
1108
        EditEdge *eed;
 
1109
        EditFace *efa;
 
1110
        short done=1, sel, toggle=0;
 
1111
 
 
1112
        if(em->edges.first==0) return;
 
1113
 
 
1114
        if(qual & LR_CTRLKEY) {
 
1115
                selectconnectedAll();
 
1116
                return;
 
1117
        }
 
1118
 
 
1119
        
 
1120
        if( unified_findnearest(&eve, &eed, &efa)==0 ) {
 
1121
                error("Nothing indicated ");
 
1122
                return;
 
1123
        }
 
1124
        
 
1125
        sel= 1;
 
1126
        if(qual & LR_SHIFTKEY) sel=0;
 
1127
 
 
1128
        /* clear test flags */
 
1129
        for(v1= em->verts.first; v1; v1= v1->next) v1->f1= 0;
 
1130
        
 
1131
        /* start vertex/face/edge */
 
1132
        if(eve) eve->f1= 1;
 
1133
        else if(eed) eed->v1->f1= eed->v2->f1= 1;
 
1134
        else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
 
1135
        
 
1136
        /* set flag f1 if affected */
 
1137
        while(done==1) {
 
1138
                done= 0;
 
1139
                toggle++;
 
1140
                
 
1141
                if(toggle & 1) eed= em->edges.first;
 
1142
                else eed= em->edges.last;
 
1143
                
 
1144
                while(eed) {
 
1145
                        v1= eed->v1;
 
1146
                        v2= eed->v2;
 
1147
                        
 
1148
                        if(eed->h==0) {
 
1149
                                if(v1->f1 && v2->f1==0) {
 
1150
                                        v2->f1= 1;
 
1151
                                        done= 1;
 
1152
                                }
 
1153
                                else if(v1->f1==0 && v2->f1) {
 
1154
                                        v1->f1= 1;
 
1155
                                        done= 1;
 
1156
                                }
 
1157
                        }
 
1158
                        
 
1159
                        if(toggle & 1) eed= eed->next;
 
1160
                        else eed= eed->prev;
 
1161
                }
 
1162
        }
 
1163
        
 
1164
        /* now use vertex f1 flag to select/deselect */
 
1165
        for(eed= em->edges.first; eed; eed= eed->next) {
 
1166
                if(eed->v1->f1 && eed->v2->f1) 
 
1167
                        EM_select_edge(eed, sel);
 
1168
        }
 
1169
        for(efa= em->faces.first; efa; efa= efa->next) {
 
1170
                if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) 
 
1171
                        EM_select_face(efa, sel);
 
1172
        }
 
1173
        /* no flush needed, connected geometry is done */
 
1174
        
 
1175
        countall();
 
1176
        
 
1177
        allqueue(REDRAWVIEW3D, 0);
 
1178
        BIF_undo_push("Select Linked");
 
1179
        
 
1180
}
 
1181
 
 
1182
/* swap is 0 or 1, if 1 it hides not selected */
 
1183
void hide_mesh(int swap)
 
1184
{
 
1185
        EditMesh *em = G.editMesh;
 
1186
        EditVert *eve;
 
1187
        EditEdge *eed;
 
1188
        EditFace *efa;
 
1189
        int a;
 
1190
        
 
1191
        if(G.obedit==0) return;
 
1192
 
 
1193
        /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
 
1194
        /*  - vertex hidden, always means edge is hidden too
 
1195
                - edge hidden, always means face is hidden too
 
1196
                - face hidden, only set face hide
 
1197
                - then only flush back down what's absolute hidden
 
1198
        */
 
1199
        if(G.scene->selectmode & SCE_SELECT_VERTEX) {
 
1200
                for(eve= em->verts.first; eve; eve= eve->next) {
 
1201
                        if((eve->f & SELECT)!=swap) {
 
1202
                                eve->xs= 3200;
 
1203
                                eve->f &= ~SELECT;
 
1204
                                eve->h= 1;
 
1205
                        }
 
1206
                }
 
1207
        
 
1208
                for(eed= em->edges.first; eed; eed= eed->next) {
 
1209
                        if(eed->v1->h || eed->v2->h) {
 
1210
                                eed->h |= 1;
 
1211
                                eed->f &= ~SELECT;
 
1212
                        }
 
1213
                }
 
1214
        
 
1215
                for(efa= em->faces.first; efa; efa= efa->next) {
 
1216
                        if(efa->e1->h || efa->e2->h || efa->e3->h || (efa->e4 && efa->e4->h)) {
 
1217
                                efa->h= 1;
 
1218
                                efa->f &= ~SELECT;
 
1219
                        }
 
1220
                }
 
1221
        }
 
1222
        else if(G.scene->selectmode & SCE_SELECT_EDGE) {
 
1223
 
 
1224
                for(eed= em->edges.first; eed; eed= eed->next) {
 
1225
                        if((eed->f & SELECT)!=swap) {
 
1226
                                eed->h |= 1;
 
1227
                                EM_select_edge(eed, 0);
 
1228
                        }
 
1229
                }
 
1230
 
 
1231
                for(efa= em->faces.first; efa; efa= efa->next) {
 
1232
                        if(efa->e1->h || efa->e2->h || efa->e3->h || (efa->e4 && efa->e4->h)) {
 
1233
                                efa->h= 1;
 
1234
                                efa->f &= ~SELECT;
 
1235
                        }
 
1236
                }
 
1237
        }
 
1238
        else {
 
1239
 
 
1240
                for(efa= em->faces.first; efa; efa= efa->next) {
 
1241
                        if((efa->f & SELECT)!=swap) {
 
1242
                                efa->h= 1;
 
1243
                                EM_select_face(efa, 0);
 
1244
                        }
 
1245
                }
 
1246
        }
 
1247
        
 
1248
        /* flush down, only whats 100% hidden */
 
1249
        for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
 
1250
        for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
 
1251
        
 
1252
        if(G.scene->selectmode & SCE_SELECT_FACE) {
 
1253
                for(efa= em->faces.first; efa; efa= efa->next) {
 
1254
                        if(efa->h) a= 1; else a= 2;
 
1255
                        efa->e1->f1 |= a;
 
1256
                        efa->e2->f1 |= a;
 
1257
                        efa->e3->f1 |= a;
 
1258
                        if(efa->e4) efa->e4->f1 |= a;
 
1259
                }
 
1260
        }
 
1261
        
 
1262
        if(G.scene->selectmode >= SCE_SELECT_EDGE) {
 
1263
                for(eed= em->edges.first; eed; eed= eed->next) {
 
1264
                        if(eed->f1==1) eed->h |= 1;
 
1265
                        if(eed->h & 1) a= 1; else a= 2;
 
1266
                        eed->v1->f1 |= a;
 
1267
                        eed->v2->f1 |= a;
 
1268
                }
 
1269
        }
 
1270
 
 
1271
        if(G.scene->selectmode >= SCE_SELECT_VERTEX) {
 
1272
                for(eve= em->verts.first; eve; eve= eve->next) {
 
1273
                        if(eve->f1==1) eve->h= 1;
 
1274
                }
 
1275
        }
 
1276
                
 
1277
        allqueue(REDRAWVIEW3D, 0);
 
1278
        makeDispList(G.obedit);
 
1279
        BIF_undo_push("Hide");
 
1280
}
 
1281
 
 
1282
 
 
1283
void reveal_mesh(void)
 
1284
{
 
1285
        EditMesh *em = G.editMesh;
 
1286
        EditVert *eve;
 
1287
        EditEdge *eed;
 
1288
        EditFace *efa;
 
1289
        
 
1290
        if(G.obedit==0) return;
 
1291
 
 
1292
        for(eve= em->verts.first; eve; eve= eve->next) {
 
1293
                if(eve->h) {
 
1294
                        eve->h= 0;
 
1295
                        eve->f |= SELECT;
 
1296
                }
 
1297
        }
 
1298
        for(eed= em->edges.first; eed; eed= eed->next) {
 
1299
                if(eed->h & 1) {
 
1300
                        eed->h &= ~1;
 
1301
                        if(G.scene->selectmode & SCE_SELECT_VERTEX); 
 
1302
                        else EM_select_edge(eed, 1);
 
1303
                }
 
1304
        }
 
1305
        for(efa= em->faces.first; efa; efa= efa->next) {
 
1306
                if(efa->h) {
 
1307
                        efa->h= 0;
 
1308
                        if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)); 
 
1309
                        else EM_select_face(efa, 1);
 
1310
                }
 
1311
        }
 
1312
 
 
1313
        EM_fgon_flags();        // redo flags and indices for fgons
 
1314
        EM_selectmode_flush();
 
1315
        
 
1316
        allqueue(REDRAWVIEW3D, 0);
 
1317
        makeDispList(G.obedit);
 
1318
        BIF_undo_push("Reveal");
 
1319
}
 
1320
 
 
1321
void select_non_manifold(void)
 
1322
{
 
1323
        EditMesh *em = G.editMesh;
 
1324
        EditVert *eve;
 
1325
        EditEdge *eed;
 
1326
        EditFace *efa;
 
1327
 
 
1328
        /* Selects isolated verts, and edges that do not have 2 neighboring
 
1329
         * faces
 
1330
         */
 
1331
        
 
1332
        if(G.scene->selectmode==SCE_SELECT_FACE) {
 
1333
                error("Doesn't work in face selection mode");
 
1334
                return;
 
1335
        }
 
1336
 
 
1337
        eve= em->verts.first;
 
1338
        while(eve) {
 
1339
                /* this will count how many edges are connected
 
1340
                 * to this vert */
 
1341
                eve->f1= 0;
 
1342
                eve= eve->next;
 
1343
        }
 
1344
 
 
1345
        eed= em->edges.first;
 
1346
        while(eed) {
 
1347
                /* this will count how many faces are connected to
 
1348
                 * this edge */
 
1349
                eed->f1= 0;
 
1350
                /* increase edge count for verts */
 
1351
                ++eed->v1->f1;
 
1352
                ++eed->v2->f1;
 
1353
                eed= eed->next;
 
1354
        }
 
1355
 
 
1356
        efa= em->faces.first;
 
1357
        while(efa) {
 
1358
                /* increase face count for edges */
 
1359
                ++efa->e1->f1;
 
1360
                ++efa->e2->f1;
 
1361
                ++efa->e3->f1;
 
1362
                if (efa->e4)
 
1363
                        ++efa->e4->f1;                  
 
1364
                efa= efa->next;
 
1365
        }
 
1366
 
 
1367
        /* select verts that are attached to an edge that does not
 
1368
         * have 2 neighboring faces */
 
1369
        eed= em->edges.first;
 
1370
        while(eed) {
 
1371
                if (eed->h==0 && eed->f1 != 2) {
 
1372
                        EM_select_edge(eed, 1);
 
1373
                }
 
1374
                eed= eed->next;
 
1375
        }
 
1376
 
 
1377
        /* select isolated verts */
 
1378
        eve= em->verts.first;
 
1379
        while(eve) {
 
1380
                if (eve->f1 == 0) {
 
1381
                        if (!eve->h) eve->f |= SELECT;
 
1382
                }
 
1383
                eve= eve->next;
 
1384
        }
 
1385
 
 
1386
        countall();
 
1387
        addqueue(curarea->win,  REDRAW, 0);
 
1388
        BIF_undo_push("Select Non Manifold");
 
1389
}
 
1390
 
 
1391
void selectswap_mesh(void) /* UI level */
 
1392
{
 
1393
        EditMesh *em = G.editMesh;
 
1394
        EditVert *eve;
 
1395
        EditEdge *eed;
 
1396
        EditFace *efa;
 
1397
        
 
1398
        if(G.scene->selectmode & SCE_SELECT_VERTEX) {
 
1399
 
 
1400
                for(eve= em->verts.first; eve; eve= eve->next) {
 
1401
                        if(eve->h==0) {
 
1402
                                if(eve->f & SELECT) eve->f &= ~SELECT;
 
1403
                                else eve->f|= SELECT;
 
1404
                        }
 
1405
                }
 
1406
        }
 
1407
        else if(G.scene->selectmode & SCE_SELECT_EDGE) {
 
1408
                for(eed= em->edges.first; eed; eed= eed->next) {
 
1409
                        if(eed->h==0) {
 
1410
                                EM_select_edge(eed, !(eed->f & SELECT));
 
1411
                        }
 
1412
                }
 
1413
        }
 
1414
        else {
 
1415
                for(efa= em->faces.first; efa; efa= efa->next) {
 
1416
                        if(efa->h==0) {
 
1417
                                EM_select_face(efa, !(efa->f & SELECT));
 
1418
                        }
 
1419
                }
 
1420
        }
 
1421
 
 
1422
        EM_selectmode_flush();
 
1423
        
 
1424
        countall();
 
1425
        allqueue(REDRAWVIEW3D, 0);
 
1426
 
 
1427
        BIF_undo_push("Select Swap");
 
1428
        
 
1429
}
 
1430
 
 
1431
void deselectall_mesh(void)      /* this toggles!!!, UI level */
 
1432
{
 
1433
        
 
1434
        if(G.obedit->lay & G.vd->lay) {
 
1435
 
 
1436
                if( EM_nvertices_selected() ) {
 
1437
                        EM_clear_flag_all(SELECT);
 
1438
                        BIF_undo_push("Deselect All");
 
1439
                }
 
1440
                else  {
 
1441
                        EM_set_flag_all(SELECT);
 
1442
                        BIF_undo_push("Select All");
 
1443
                }
 
1444
                
 
1445
                countall();
 
1446
                allqueue(REDRAWVIEW3D, 0);
 
1447
        }
 
1448
}
 
1449
 
 
1450
void select_more(void)
 
1451
{
 
1452
        EditMesh *em = G.editMesh;
 
1453
        EditVert *eve;
 
1454
        EditEdge *eed;
 
1455
        EditFace *efa;
 
1456
        
 
1457
        for(eve= em->verts.first; eve; eve= eve->next) {
 
1458
                if(eve->f & SELECT) eve->f1= 1;
 
1459
                else eve->f1 = 0;
 
1460
        }
 
1461
        
 
1462
        /* set f1 flags in vertices to select 'more' */
 
1463
        for(eed= em->edges.first; eed; eed= eed->next) {
 
1464
                if(eed->h==0) {
 
1465
                        if (eed->v1->f & SELECT)
 
1466
                                eed->v2->f1 = 1;
 
1467
                        if (eed->v2->f & SELECT)
 
1468
                                eed->v1->f1 = 1;
 
1469
                }
 
1470
        }
 
1471
 
 
1472
        /* new selected edges, but not in facemode */
 
1473
        if(G.scene->selectmode <= SCE_SELECT_EDGE) {
 
1474
                
 
1475
                for(eed= em->edges.first; eed; eed= eed->next) {
 
1476
                        if(eed->h==0) {
 
1477
                                if(eed->v1->f1 && eed->v2->f1) EM_select_edge(eed, 1);
 
1478
                        }
 
1479
                }
 
1480
        }
 
1481
        /* new selected faces */
 
1482
        for(efa= em->faces.first; efa; efa= efa->next) {
 
1483
                if(efa->h==0) {
 
1484
                        if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) 
 
1485
                                EM_select_face(efa, 1);
 
1486
                }
 
1487
        }
 
1488
 
 
1489
        countall();
 
1490
        addqueue(curarea->win,  REDRAW, 0);
 
1491
        BIF_undo_push("Select More");
 
1492
}
 
1493
 
 
1494
void select_less(void)
 
1495
{
 
1496
        EditMesh *em = G.editMesh;
 
1497
        EditEdge *eed;
 
1498
        EditFace *efa;
 
1499
 
 
1500
        if(G.scene->selectmode <= SCE_SELECT_EDGE) {
 
1501
                /* eed->f1 == 1:  edge with a selected and deselected vert */ 
 
1502
 
 
1503
                for(eed= em->edges.first; eed; eed= eed->next) {
 
1504
                        eed->f1= 0;
 
1505
                        if(eed->h==0) {
 
1506
                                
 
1507
                                if ( !(eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) 
 
1508
                                        eed->f1= 1;
 
1509
                                if ( (eed->v1->f & SELECT) && !(eed->v2->f & SELECT) ) 
 
1510
                                        eed->f1= 1;
 
1511
                        }
 
1512
                }
 
1513
                
 
1514
                /* deselect edges with flag set */
 
1515
                for(eed= em->edges.first; eed; eed= eed->next) {
 
1516
                        if (eed->h==0 && eed->f1 == 1) {
 
1517
                                EM_select_edge(eed, 0);
 
1518
                        }
 
1519
                }
 
1520
                EM_deselect_flush();
 
1521
                
 
1522
        }
 
1523
        else {
 
1524
                /* deselect faces with 1 or more deselect edges */
 
1525
                /* eed->f1 == mixed selection edge */
 
1526
                for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
 
1527
 
 
1528
                for(efa= em->faces.first; efa; efa= efa->next) {
 
1529
                        if(efa->h==0) {
 
1530
                                if(efa->f & SELECT) {
 
1531
                                        efa->e1->f1 |= 1;
 
1532
                                        efa->e2->f1 |= 1;
 
1533
                                        efa->e3->f1 |= 1;
 
1534
                                        if(efa->e4) efa->e4->f1 |= 1;
 
1535
                                }
 
1536
                                else {
 
1537
                                        efa->e1->f1 |= 2;
 
1538
                                        efa->e2->f1 |= 2;
 
1539
                                        efa->e3->f1 |= 2;
 
1540
                                        if(efa->e4) efa->e4->f1 |= 2;
 
1541
                                }
 
1542
                        }
 
1543
                }
 
1544
                for(efa= em->faces.first; efa; efa= efa->next) {
 
1545
                        if(efa->h==0) {
 
1546
                                if(efa->e1->f1==3 || efa->e2->f1==3 || efa->e3->f1==3 || (efa->e4 && efa->e4->f1==3)) { 
 
1547
                                        EM_select_face(efa, 0);
 
1548
                                }
 
1549
                        }
 
1550
                }
 
1551
                EM_selectmode_flush();
 
1552
                
 
1553
        }
 
1554
        
 
1555
        countall();
 
1556
        allqueue(REDRAWVIEW3D, 0);
 
1557
}
 
1558
 
 
1559
 
 
1560
void selectrandom_mesh(void) /* randomly selects a user-set % of vertices/edges/faces */
 
1561
{
 
1562
        EditMesh *em = G.editMesh;
 
1563
        EditVert *eve;
 
1564
        EditEdge *eed;
 
1565
        EditFace *efa;
 
1566
        short randfac = 50;
 
1567
 
 
1568
        if(G.obedit==NULL || (G.obedit->lay & G.vd->lay)==0) return;
 
1569
 
 
1570
        /* Get the percentage of vertices to randomly select as 'randfac' */
 
1571
        if(button(&randfac,0, 100,"Percentage:")==0) return;
 
1572
 
 
1573
        BLI_srand( BLI_rand() ); /* random seed */
 
1574
        
 
1575
        if(G.scene->selectmode & SCE_SELECT_VERTEX) {
 
1576
                for(eve= em->verts.first; eve; eve= eve->next) {
 
1577
                        if(eve->h==0) {
 
1578
                                if ( (BLI_frand() * 100) < randfac) 
 
1579
                                        eve->f |= SELECT;
 
1580
                        }
 
1581
                }
 
1582
        }
 
1583
        else if(G.scene->selectmode & SCE_SELECT_EDGE) {
 
1584
                for(eed= em->edges.first; eed; eed= eed->next) {
 
1585
                        if(eed->h==0) {
 
1586
                                if ( (BLI_frand() * 100) < randfac) 
 
1587
                                        EM_select_edge(eed, 1);
 
1588
                        }
 
1589
                }
 
1590
        }
 
1591
        else {
 
1592
                for(efa= em->faces.first; efa; efa= efa->next) {
 
1593
                        if(efa->h==0) {
 
1594
                                if ( (BLI_frand() * 100) < randfac) 
 
1595
                                        EM_select_face(efa, 1);
 
1596
                        }
 
1597
                }
 
1598
        }
 
1599
        
 
1600
        EM_selectmode_flush();
 
1601
 
 
1602
        countall();
 
1603
        allqueue(REDRAWVIEW3D, 0);
 
1604
}
 
1605
 
 
1606
void editmesh_select_by_material(int index) 
 
1607
{
 
1608
        EditMesh *em = G.editMesh;
 
1609
        EditFace *efa;
 
1610
        
 
1611
        for (efa=em->faces.first; efa; efa= efa->next) {
 
1612
                if (efa->mat_nr==index) {
 
1613
                        EM_select_face(efa, 1);
 
1614
                }
 
1615
        }
 
1616
 
 
1617
        EM_selectmode_flush();
 
1618
}
 
1619
 
 
1620
void editmesh_deselect_by_material(int index) 
 
1621
{
 
1622
        EditMesh *em = G.editMesh;
 
1623
        EditFace *efa;
 
1624
        
 
1625
        for (efa=em->faces.first; efa; efa= efa->next) {
 
1626
                if (efa->mat_nr==index) {
 
1627
                        EM_select_face(efa, 0);
 
1628
                }
 
1629
        }
 
1630
 
 
1631
        EM_selectmode_flush();
 
1632
}
 
1633
 
 
1634
void EM_selectmode_menu(void)
 
1635
{
 
1636
        int val;
 
1637
        
 
1638
        if(G.scene->selectmode & SCE_SELECT_VERTEX) pupmenu_set_active(1);
 
1639
        else if(G.scene->selectmode & SCE_SELECT_EDGE) pupmenu_set_active(2);
 
1640
        else pupmenu_set_active(3);
 
1641
        
 
1642
        val= pupmenu("Select Mode%t|Vertices|Edges|Faces");
 
1643
        if(val>0) {
 
1644
                if(val==1) G.scene->selectmode= SCE_SELECT_VERTEX;
 
1645
                else if(val==2) G.scene->selectmode= SCE_SELECT_EDGE;
 
1646
                else G.scene->selectmode= SCE_SELECT_FACE;
 
1647
        
 
1648
                EM_selectmode_set(); // when mode changes
 
1649
                allqueue(REDRAWVIEW3D, 1);
 
1650
        }
 
1651
}
 
1652
 
 
1653
/* ************************* SEAMS AND EDGES **************** */
 
1654
 
 
1655
void editmesh_mark_seam(int clear)
 
1656
{
 
1657
        EditMesh *em= G.editMesh;
 
1658
        EditEdge *eed;
 
1659
        Mesh *me= G.obedit->data;
 
1660
 
 
1661
        /* auto-enable seams drawing */
 
1662
        if(clear==0) {
 
1663
                if(!(G.f & G_DRAWSEAMS)) {
 
1664
                        G.f |= G_DRAWSEAMS;
 
1665
                        allqueue(REDRAWBUTSEDIT, 0);
 
1666
                }
 
1667
                if(!me->medge)
 
1668
                        me->medge= MEM_callocN(sizeof(MEdge), "fake mesh edge");
 
1669
        }
 
1670
 
 
1671
        if(clear) {
 
1672
                eed= em->edges.first;
 
1673
                while(eed) {
 
1674
                        if((eed->h==0) && (eed->f & SELECT)) {
 
1675
                                eed->seam = 0;
 
1676
                        }
 
1677
                        eed= eed->next;
 
1678
                }
 
1679
                BIF_undo_push("Mark Seam");
 
1680
        }
 
1681
        else {
 
1682
                eed= em->edges.first;
 
1683
                while(eed) {
 
1684
                        if((eed->h==0) && (eed->f & SELECT)) {
 
1685
                                eed->seam = 1;
 
1686
                        }
 
1687
                        eed= eed->next;
 
1688
                }
 
1689
                BIF_undo_push("Clear Seam");
 
1690
        }
 
1691
 
 
1692
        allqueue(REDRAWVIEW3D, 0);
 
1693
}
 
1694
 
 
1695
void Edge_Menu() {
 
1696
        short ret;
 
1697
 
 
1698
        ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4");
 
1699
 
 
1700
        switch(ret)
 
1701
        {
 
1702
        case 1:
 
1703
                editmesh_mark_seam(0);
 
1704
                break;
 
1705
        case 2:
 
1706
                editmesh_mark_seam(1);
 
1707
                break;
 
1708
        case 3:
 
1709
                edge_rotate_selected(2);
 
1710
                break;
 
1711
        case 4:
 
1712
                edge_rotate_selected(1);
 
1713
                break;
 
1714
        }
 
1715
}
 
1716
 
 
1717
 
 
1718
/* **************** NORMALS ************** */
 
1719
 
 
1720
void righthandfaces(int select) /* makes faces righthand turning */
 
1721
{
 
1722
        EditMesh *em = G.editMesh;
 
1723
        EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
 
1724
        EditFace *efa, *startvl;
 
1725
        float maxx, nor[3], cent[3];
 
1726
        int totsel, found, foundone, direct, turn, tria_nr;
 
1727
 
 
1728
   /* based at a select-connected to witness loose objects */
 
1729
 
 
1730
        /* count per edge the amount of faces */
 
1731
 
 
1732
        /* find the ultimate left, front, upper face (not manhattan dist!!) */
 
1733
        /* also evaluate both triangle cases in quad, since these can be non-flat */
 
1734
 
 
1735
        /* put normal to the outside, and set the first direction flags in edges */
 
1736
 
 
1737
        /* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
 
1738
        /* this is in fact the 'select connected' */
 
1739
        
 
1740
        /* in case (selected) faces were not done: start over with 'find the ultimate ...' */
 
1741
 
 
1742
        waitcursor(1);
 
1743
        
 
1744
        eed= em->edges.first;
 
1745
        while(eed) {
 
1746
                eed->f2= 0;             // edge direction
 
1747
                eed->f1= 0;             // counter
 
1748
                eed= eed->next;
 
1749
        }
 
1750
 
 
1751
        /* count faces and edges */
 
1752
        totsel= 0;
 
1753
        efa= em->faces.first;
 
1754
        while(efa) {
 
1755
                if(select==0 || (efa->f & SELECT) ) {
 
1756
                        efa->f1= 1;
 
1757
                        totsel++;
 
1758
                        efa->e1->f1++;
 
1759
                        efa->e2->f1++;
 
1760
                        efa->e3->f1++;
 
1761
                        if(efa->v4) efa->e4->f1++;
 
1762
                }
 
1763
                else efa->f1= 0;
 
1764
 
 
1765
                efa= efa->next;
 
1766
        }
 
1767
 
 
1768
        while(totsel>0) {
 
1769
                /* from the outside to the inside */
 
1770
 
 
1771
                efa= em->faces.first;
 
1772
                startvl= NULL;
 
1773
                maxx= -1.0e10;
 
1774
                tria_nr= 0;
 
1775
 
 
1776
                while(efa) {
 
1777
                        if(efa->f1) {
 
1778
                                CalcCent3f(cent, efa->v1->co, efa->v2->co, efa->v3->co);
 
1779
                                cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
 
1780
                                
 
1781
                                if(cent[0]>maxx) {
 
1782
                                        maxx= cent[0];
 
1783
                                        startvl= efa;
 
1784
                                        tria_nr= 0;
 
1785
                                }
 
1786
                                if(efa->v4) {
 
1787
                                        CalcCent3f(cent, efa->v1->co, efa->v3->co, efa->v4->co);
 
1788
                                        cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
 
1789
                                        
 
1790
                                        if(cent[0]>maxx) {
 
1791
                                                maxx= cent[0];
 
1792
                                                startvl= efa;
 
1793
                                                tria_nr= 1;
 
1794
                                        }
 
1795
                                }
 
1796
                        }
 
1797
                        efa= efa->next;
 
1798
                }
 
1799
                
 
1800
                /* set first face correct: calc normal */
 
1801
                
 
1802
                if(tria_nr==1) {
 
1803
                        CalcNormFloat(startvl->v1->co, startvl->v3->co, startvl->v4->co, nor);
 
1804
                        CalcCent3f(cent, startvl->v1->co, startvl->v3->co, startvl->v4->co);
 
1805
                } else {
 
1806
                        CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, nor);
 
1807
                        CalcCent3f(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
 
1808
                }
 
1809
                /* first normal is oriented this way or the other */
 
1810
                if(select) {
 
1811
                        if(select==2) {
 
1812
                                if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipface(startvl);
 
1813
                        }
 
1814
                        else {
 
1815
                                if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(startvl);
 
1816
                        }
 
1817
                }
 
1818
                else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(startvl);
 
1819
 
 
1820
 
 
1821
                eed= startvl->e1;
 
1822
                if(eed->v1==startvl->v1) eed->f2= 1; 
 
1823
                else eed->f2= 2;
 
1824
                
 
1825
                eed= startvl->e2;
 
1826
                if(eed->v1==startvl->v2) eed->f2= 1; 
 
1827
                else eed->f2= 2;
 
1828
                
 
1829
                eed= startvl->e3;
 
1830
                if(eed->v1==startvl->v3) eed->f2= 1; 
 
1831
                else eed->f2= 2;
 
1832
                
 
1833
                eed= startvl->e4;
 
1834
                if(eed) {
 
1835
                        if(eed->v1==startvl->v4) eed->f2= 1; 
 
1836
                        else eed->f2= 2;
 
1837
                }
 
1838
                
 
1839
                startvl->f1= 0;
 
1840
                totsel--;
 
1841
 
 
1842
                /* test normals */
 
1843
                found= 1;
 
1844
                direct= 1;
 
1845
                while(found) {
 
1846
                        found= 0;
 
1847
                        if(direct) efa= em->faces.first;
 
1848
                        else efa= em->faces.last;
 
1849
                        while(efa) {
 
1850
                                if(efa->f1) {
 
1851
                                        turn= 0;
 
1852
                                        foundone= 0;
 
1853
 
 
1854
                                        ed1= efa->e1;
 
1855
                                        ed2= efa->e2;
 
1856
                                        ed3= efa->e3;
 
1857
                                        ed4= efa->e4;
 
1858
 
 
1859
                                        if(ed1->f2) {
 
1860
                                                if(ed1->v1==efa->v1 && ed1->f2==1) turn= 1;
 
1861
                                                if(ed1->v2==efa->v1 && ed1->f2==2) turn= 1;
 
1862
                                                foundone= 1;
 
1863
                                        }
 
1864
                                        else if(ed2->f2) {
 
1865
                                                if(ed2->v1==efa->v2 && ed2->f2==1) turn= 1;
 
1866
                                                if(ed2->v2==efa->v2 && ed2->f2==2) turn= 1;
 
1867
                                                foundone= 1;
 
1868
                                        }
 
1869
                                        else if(ed3->f2) {
 
1870
                                                if(ed3->v1==efa->v3 && ed3->f2==1) turn= 1;
 
1871
                                                if(ed3->v2==efa->v3 && ed3->f2==2) turn= 1;
 
1872
                                                foundone= 1;
 
1873
                                        }
 
1874
                                        else if(ed4 && ed4->f2) {
 
1875
                                                if(ed4->v1==efa->v4 && ed4->f2==1) turn= 1;
 
1876
                                                if(ed4->v2==efa->v4 && ed4->f2==2) turn= 1;
 
1877
                                                foundone= 1;
 
1878
                                        }
 
1879
 
 
1880
                                        if(foundone) {
 
1881
                                                found= 1;
 
1882
                                                totsel--;
 
1883
                                                efa->f1= 0;
 
1884
 
 
1885
                                                if(turn) {
 
1886
                                                        if(ed1->v1==efa->v1) ed1->f2= 2; 
 
1887
                                                        else ed1->f2= 1;
 
1888
                                                        if(ed2->v1==efa->v2) ed2->f2= 2; 
 
1889
                                                        else ed2->f2= 1;
 
1890
                                                        if(ed3->v1==efa->v3) ed3->f2= 2; 
 
1891
                                                        else ed3->f2= 1;
 
1892
                                                        if(ed4) {
 
1893
                                                                if(ed4->v1==efa->v4) ed4->f2= 2; 
 
1894
                                                                else ed4->f2= 1;
 
1895
                                                        }
 
1896
 
 
1897
                                                        flipface(efa);
 
1898
 
 
1899
                                                }
 
1900
                                                else {
 
1901
                                                        if(ed1->v1== efa->v1) ed1->f2= 1; 
 
1902
                                                        else ed1->f2= 2;
 
1903
                                                        if(ed2->v1==efa->v2) ed2->f2= 1; 
 
1904
                                                        else ed2->f2= 2;
 
1905
                                                        if(ed3->v1==efa->v3) ed3->f2= 1; 
 
1906
                                                        else ed3->f2= 2;
 
1907
                                                        if(ed4) {
 
1908
                                                                if(ed4->v1==efa->v4) ed4->f2= 1; 
 
1909
                                                                else ed4->f2= 2;
 
1910
                                                        }
 
1911
                                                }
 
1912
                                        }
 
1913
                                }
 
1914
                                if(direct) efa= efa->next;
 
1915
                                else efa= efa->prev;
 
1916
                        }
 
1917
                        direct= 1-direct;
 
1918
                }
 
1919
        }
 
1920
 
 
1921
        recalc_editnormals();
 
1922
        
 
1923
        makeDispList(G.obedit);
 
1924
        
 
1925
        waitcursor(0);
 
1926
}
 
1927
 
 
1928
 
 
1929
/* ********** ALIGN WITH VIEW **************** */
 
1930
 
 
1931
 
 
1932
static void editmesh_calc_selvert_center(float cent_r[3])
 
1933
{
 
1934
        EditMesh *em = G.editMesh;
 
1935
        EditVert *eve;
 
1936
        int nsel= 0;
 
1937
 
 
1938
        cent_r[0]= cent_r[1]= cent_r[0]= 0.0;
 
1939
 
 
1940
        for (eve= em->verts.first; eve; eve= eve->next) {
 
1941
                if (eve->f & SELECT) {
 
1942
                        cent_r[0]+= eve->co[0];
 
1943
                        cent_r[1]+= eve->co[1];
 
1944
                        cent_r[2]+= eve->co[2];
 
1945
                        nsel++;
 
1946
                }
 
1947
        }
 
1948
 
 
1949
        if (nsel) {
 
1950
                cent_r[0]/= nsel;
 
1951
                cent_r[1]/= nsel;
 
1952
                cent_r[2]/= nsel;
 
1953
        }
 
1954
}
 
1955
 
 
1956
static int tface_is_selected(TFace *tf)
 
1957
{
 
1958
        return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT));
 
1959
}
 
1960
 
 
1961
static int faceselect_nfaces_selected(Mesh *me)
 
1962
{
 
1963
        int i, count= 0;
 
1964
 
 
1965
        for (i=0; i<me->totface; i++) {
 
1966
                MFace *mf= ((MFace*) me->mface) + i;
 
1967
                TFace *tf= ((TFace*) me->tface) + i;
 
1968
 
 
1969
                if (mf->v3 && tface_is_selected(tf))
 
1970
                        count++;
 
1971
        }
 
1972
 
 
1973
        return count;
 
1974
}
 
1975
 
 
1976
        /* XXX, code for both these functions should be abstract,
 
1977
         * then unified, then written for other things (like objects,
 
1978
         * which would use same as vertices method), then added
 
1979
         * to interface! Hoera! - zr
 
1980
         */
 
1981
void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis)
 
1982
{
 
1983
        if (!faceselect_nfaces_selected(me)) {
 
1984
                error("No faces selected.");
 
1985
        } else {
 
1986
                float norm[3];
 
1987
                int i;
 
1988
 
 
1989
                norm[0]= norm[1]= norm[2]= 0.0;
 
1990
                for (i=0; i<me->totface; i++) {
 
1991
                        MFace *mf= ((MFace*) me->mface) + i;
 
1992
                        TFace *tf= ((TFace*) me->tface) + i;
 
1993
        
 
1994
                        if (mf->v3 && tface_is_selected(tf)) {
 
1995
                                float *v1, *v2, *v3, fno[3];
 
1996
 
 
1997
                                v1= me->mvert[mf->v1].co;
 
1998
                                v2= me->mvert[mf->v2].co;
 
1999
                                v3= me->mvert[mf->v3].co;
 
2000
                                if (mf->v4) {
 
2001
                                        float *v4= me->mvert[mf->v4].co;
 
2002
                                        CalcNormFloat4(v1, v2, v3, v4, fno);
 
2003
                                } else {
 
2004
                                        CalcNormFloat(v1, v2, v3, fno);
 
2005
                                }
 
2006
 
 
2007
                                norm[0]+= fno[0];
 
2008
                                norm[1]+= fno[1];
 
2009
                                norm[2]+= fno[2];
 
2010
                        }
 
2011
                }
 
2012
 
 
2013
                view3d_align_axis_to_vector(v3d, axis, norm);
 
2014
        }
 
2015
}
 
2016
 
 
2017
void editmesh_align_view_to_selected(View3D *v3d, int axis)
 
2018
{
 
2019
        EditMesh *em = G.editMesh;
 
2020
        int nselverts= EM_nvertices_selected();
 
2021
 
 
2022
        if (nselverts<3) {
 
2023
                if (nselverts==0) {
 
2024
                        error("No faces or vertices selected.");
 
2025
                } else {
 
2026
                        error("At least one face or three vertices must be selected.");
 
2027
                }
 
2028
        } else if (EM_nfaces_selected()) {
 
2029
                float norm[3];
 
2030
                EditFace *efa;
 
2031
 
 
2032
                norm[0]= norm[1]= norm[2]= 0.0;
 
2033
                for (efa= em->faces.first; efa; efa= efa->next) {
 
2034
                        if (faceselectedAND(efa, SELECT)) {
 
2035
                                float fno[3];
 
2036
                                if (efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, fno);
 
2037
                                else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, fno);
 
2038
                                                /* XXX, fixme, should be flipped intp a 
 
2039
                                                 * consistent direction. -zr
 
2040
                                                 */
 
2041
                                norm[0]+= fno[0];
 
2042
                                norm[1]+= fno[1];
 
2043
                                norm[2]+= fno[2];
 
2044
                        }
 
2045
                }
 
2046
 
 
2047
                Mat4Mul3Vecfl(G.obedit->obmat, norm);
 
2048
                view3d_align_axis_to_vector(v3d, axis, norm);
 
2049
        } else {
 
2050
                float cent[3], norm[3];
 
2051
                EditVert *eve, *leve= NULL;
 
2052
 
 
2053
                norm[0]= norm[1]= norm[2]= 0.0;
 
2054
                editmesh_calc_selvert_center(cent);
 
2055
                for (eve= em->verts.first; eve; eve= eve->next) {
 
2056
                        if (eve->f & SELECT) {
 
2057
                                if (leve) {
 
2058
                                        float tno[3];
 
2059
                                        CalcNormFloat(cent, leve->co, eve->co, tno);
 
2060
                                        
 
2061
                                                /* XXX, fixme, should be flipped intp a 
 
2062
                                                 * consistent direction. -zr
 
2063
                                                 */
 
2064
                                        norm[0]+= tno[0];
 
2065
                                        norm[1]+= tno[1];
 
2066
                                        norm[2]+= tno[2];
 
2067
                                }
 
2068
                                leve= eve;
 
2069
                        }
 
2070
                }
 
2071
 
 
2072
                Mat4Mul3Vecfl(G.obedit->obmat, norm);
 
2073
                view3d_align_axis_to_vector(v3d, axis, norm);
 
2074
        }
 
2075
}
 
2076
 
 
2077
/* **************** VERTEX DEFORMS *************** */
 
2078
 
 
2079
void vertexsmooth(void)
 
2080
{
 
2081
        EditMesh *em = G.editMesh;
 
2082
        EditVert *eve;
 
2083
        EditEdge *eed;
 
2084
        float *adror, *adr, fac;
 
2085
        float fvec[3];
 
2086
        int teller=0;
 
2087
 
 
2088
        if(G.obedit==0) return;
 
2089
 
 
2090
        /* count */
 
2091
        eve= em->verts.first;
 
2092
        while(eve) {
 
2093
                if(eve->f & SELECT) teller++;
 
2094
                eve= eve->next;
 
2095
        }
 
2096
        if(teller==0) return;
 
2097
        
 
2098
        adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
 
2099
        eve= em->verts.first;
 
2100
        while(eve) {
 
2101
                if(eve->f & SELECT) {
 
2102
                        eve->vn= (EditVert *)adr;
 
2103
                        eve->f1= 0;
 
2104
                        adr+= 3;
 
2105
                }
 
2106
                eve= eve->next;
 
2107
        }
 
2108
        
 
2109
        eed= em->edges.first;
 
2110
        while(eed) {
 
2111
                if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) ) {
 
2112
                        fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
 
2113
                        fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
 
2114
                        fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
 
2115
                        
 
2116
                        if((eed->v1->f & SELECT) && eed->v1->f1<255) {
 
2117
                                eed->v1->f1++;
 
2118
                                VecAddf((float *)eed->v1->vn, (float *)eed->v1->vn, fvec);
 
2119
                        }
 
2120
                        if((eed->v2->f & SELECT) && eed->v2->f1<255) {
 
2121
                                eed->v2->f1++;
 
2122
                                VecAddf((float *)eed->v2->vn, (float *)eed->v2->vn, fvec);
 
2123
                        }
 
2124
                }
 
2125
                eed= eed->next;
 
2126
        }
 
2127
 
 
2128
        eve= em->verts.first;
 
2129
        while(eve) {
 
2130
                if(eve->f & SELECT) {
 
2131
                        if(eve->f1) {
 
2132
                                adr= (float *)eve->vn;
 
2133
                                fac= 0.5/(float)eve->f1;
 
2134
                                
 
2135
                                eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
 
2136
                                eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
 
2137
                                eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
 
2138
                        }
 
2139
                        eve->vn= 0;
 
2140
                }
 
2141
                eve= eve->next;
 
2142
        }
 
2143
        MEM_freeN(adror);
 
2144
 
 
2145
        recalc_editnormals();
 
2146
 
 
2147
        allqueue(REDRAWVIEW3D, 0);
 
2148
        makeDispList(G.obedit);
 
2149
        BIF_undo_push("Vertex Smooth");
 
2150
}
 
2151
 
 
2152
void vertexnoise(void)
 
2153
{
 
2154
        EditMesh *em = G.editMesh;
 
2155
        Material *ma;
 
2156
        Tex *tex;
 
2157
        EditVert *eve;
 
2158
        float b2, ofs, vec[3];
 
2159
 
 
2160
        if(G.obedit==0) return;
 
2161
        
 
2162
        ma= give_current_material(G.obedit, G.obedit->actcol);
 
2163
        if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
 
2164
                return;
 
2165
        }
 
2166
        tex= ma->mtex[0]->tex;
 
2167
        
 
2168
        ofs= tex->turbul/200.0;
 
2169
        
 
2170
        eve= (struct EditVert *)em->verts.first;
 
2171
        while(eve) {
 
2172
                if(eve->f & SELECT) {
 
2173
                        
 
2174
                        if(tex->type==TEX_STUCCI) {
 
2175
                                
 
2176
                                b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]);
 
2177
                                if(tex->stype) ofs*=(b2*b2);
 
2178
                                vec[0]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2]));
 
2179
                                vec[1]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2]));
 
2180
                                vec[2]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs));
 
2181
                                
 
2182
                                VecAddf(eve->co, eve->co, vec);
 
2183
                        }
 
2184
                        else {
 
2185
                                float tin, dum;
 
2186
                                externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum);
 
2187
                                eve->co[2]+= 0.05*tin;
 
2188
                        }
 
2189
                }
 
2190
                eve= eve->next;
 
2191
        }
 
2192
 
 
2193
        recalc_editnormals();
 
2194
        allqueue(REDRAWVIEW3D, 0);
 
2195
        makeDispList(G.obedit);
 
2196
        BIF_undo_push("Vertex Noise");
 
2197
}
 
2198
 
 
2199
void vertices_to_sphere(void)
 
2200
{
 
2201
        EditMesh *em = G.editMesh;
 
2202
        EditVert *eve;
 
2203
        Object *ob= OBACT;
 
2204
        float *curs, len, vec[3], cent[3], fac, facm, imat[3][3], bmat[3][3];
 
2205
        int tot;
 
2206
        short perc=100;
 
2207
        
 
2208
        if(ob==0) return;
 
2209
        TEST_EDITMESH
 
2210
        
 
2211
        if(button(&perc, 1, 100, "Percentage:")==0) return;
 
2212
        
 
2213
        fac= perc/100.0;
 
2214
        facm= 1.0-fac;
 
2215
        
 
2216
        Mat3CpyMat4(bmat, ob->obmat);
 
2217
        Mat3Inv(imat, bmat);
 
2218
 
 
2219
        /* centre */
 
2220
        curs= give_cursor();
 
2221
        cent[0]= curs[0]-ob->obmat[3][0];
 
2222
        cent[1]= curs[1]-ob->obmat[3][1];
 
2223
        cent[2]= curs[2]-ob->obmat[3][2];
 
2224
        Mat3MulVecfl(imat, cent);
 
2225
 
 
2226
        len= 0.0;
 
2227
        tot= 0;
 
2228
        eve= em->verts.first;
 
2229
        while(eve) {
 
2230
                if(eve->f & SELECT) {
 
2231
                        tot++;
 
2232
                        len+= VecLenf(cent, eve->co);
 
2233
                }
 
2234
                eve= eve->next;
 
2235
        }
 
2236
        len/=tot;
 
2237
        
 
2238
        if(len==0.0) len= 10.0;
 
2239
        
 
2240
        eve= em->verts.first;
 
2241
        while(eve) {
 
2242
                if(eve->f & SELECT) {
 
2243
                        vec[0]= eve->co[0]-cent[0];
 
2244
                        vec[1]= eve->co[1]-cent[1];
 
2245
                        vec[2]= eve->co[2]-cent[2];
 
2246
                        
 
2247
                        Normalise(vec);
 
2248
                        
 
2249
                        eve->co[0]= fac*(cent[0]+vec[0]*len) + facm*eve->co[0];
 
2250
                        eve->co[1]= fac*(cent[1]+vec[1]*len) + facm*eve->co[1];
 
2251
                        eve->co[2]= fac*(cent[2]+vec[2]*len) + facm*eve->co[2];
 
2252
                        
 
2253
                }
 
2254
                eve= eve->next;
 
2255
        }
 
2256
        
 
2257
        recalc_editnormals();
 
2258
        allqueue(REDRAWVIEW3D, 0);
 
2259
        makeDispList(G.obedit);
 
2260
        BIF_undo_push("To Sphere");
 
2261
}
 
2262