Cleanup: remove redundant, invalid info from headers
[blender.git] / source / blender / editors / mesh / editface.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file blender/editors/mesh/editface.c
18  *  \ingroup edmesh
19  */
20
21 #include "MEM_guardedalloc.h"
22
23 #include "BLI_blenlib.h"
24 #include "BLI_math.h"
25 #include "BLI_bitmap.h"
26
27 #include "IMB_imbuf_types.h"
28 #include "IMB_imbuf.h"
29
30 #include "DNA_mesh_types.h"
31 #include "DNA_object_types.h"
32
33 #include "BKE_DerivedMesh.h"
34 #include "BKE_global.h"
35 #include "BKE_mesh.h"
36 #include "BKE_context.h"
37
38 #include "BIF_gl.h"
39
40 #include "ED_mesh.h"
41 #include "ED_screen.h"
42 #include "ED_view3d.h"
43
44 #include "WM_api.h"
45 #include "WM_types.h"
46
47 #include "GPU_draw.h"
48 #include "GPU_buffers.h"
49
50 /* own include */
51
52 /* copy the face flags, most importantly selection from the mesh to the final derived mesh,
53  * use in object mode when selecting faces (while painting) */
54 void paintface_flush_flags(Object *ob, short flag)
55 {
56         Mesh *me = BKE_mesh_from_object(ob);
57         DerivedMesh *dm = ob->derivedFinal;
58         MPoly *polys, *mp_orig;
59         const int *index_array = NULL;
60         int totpoly;
61         int i;
62
63         BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
64
65         if (me == NULL)
66                 return;
67
68         /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */
69
70         /* we could call this directly in all areas that change selection,
71          * since this could become slow for realtime updates (circle-select for eg) */
72         if (flag & SELECT) {
73                 BKE_mesh_flush_select_from_polys(me);
74         }
75
76         if (dm == NULL)
77                 return;
78
79         /* Mesh polys => Final derived polys */
80
81         if ((index_array = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX))) {
82                 polys = dm->getPolyArray(dm);
83                 totpoly = dm->getNumPolys(dm);
84
85                 /* loop over final derived polys */
86                 for (i = 0; i < totpoly; i++) {
87                         if (index_array[i] != ORIGINDEX_NONE) {
88                                 /* Copy flags onto the final derived poly from the original mesh poly */
89                                 mp_orig = me->mpoly + index_array[i];
90                                 polys[i].flag = mp_orig->flag;
91
92                         }
93                 }
94         }
95
96         if (flag & ME_HIDE) {
97                 /* draw-object caches hidden faces, force re-generation T46867 */
98                 GPU_drawobject_free(dm);
99         }
100 }
101
102 void paintface_hide(Object *ob, const bool unselected)
103 {
104         Mesh *me;
105         MPoly *mpoly;
106         int a;
107
108         me = BKE_mesh_from_object(ob);
109         if (me == NULL || me->totpoly == 0) return;
110
111         mpoly = me->mpoly;
112         a = me->totpoly;
113         while (a--) {
114                 if ((mpoly->flag & ME_HIDE) == 0) {
115                         if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
116                                 mpoly->flag |= ME_HIDE;
117                         }
118                 }
119
120                 if (mpoly->flag & ME_HIDE) {
121                         mpoly->flag &= ~ME_FACE_SEL;
122                 }
123
124                 mpoly++;
125         }
126
127         BKE_mesh_flush_hidden_from_polys(me);
128
129         paintface_flush_flags(ob, SELECT | ME_HIDE);
130 }
131
132
133 void paintface_reveal(Object *ob, const bool select)
134 {
135         Mesh *me;
136         MPoly *mpoly;
137         int a;
138
139         me = BKE_mesh_from_object(ob);
140         if (me == NULL || me->totpoly == 0) return;
141
142         mpoly = me->mpoly;
143         a = me->totpoly;
144         while (a--) {
145                 if (mpoly->flag & ME_HIDE) {
146                         SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL);
147                         mpoly->flag &= ~ME_HIDE;
148                 }
149                 mpoly++;
150         }
151
152         BKE_mesh_flush_hidden_from_polys(me);
153
154         paintface_flush_flags(ob, SELECT | ME_HIDE);
155 }
156
157 /* Set tface seams based on edge data, uses hash table to find seam edges. */
158
159 static void select_linked_tfaces_with_seams(Mesh *me, const unsigned int index, const bool select)
160 {
161         MPoly *mp;
162         MLoop *ml;
163         int a, b;
164         bool do_it = true;
165         bool mark = false;
166
167         BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__);
168         BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__);
169
170         if (index != (unsigned int)-1) {
171                 /* only put face under cursor in array */
172                 mp = &me->mpoly[index];
173                 BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
174                 BLI_BITMAP_ENABLE(poly_tag, index);
175         }
176         else {
177                 /* fill array by selection */
178                 mp = me->mpoly;
179                 for (a = 0; a < me->totpoly; a++, mp++) {
180                         if (mp->flag & ME_HIDE) {
181                                 /* pass */
182                         }
183                         else if (mp->flag & ME_FACE_SEL) {
184                                 BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
185                                 BLI_BITMAP_ENABLE(poly_tag, a);
186                         }
187                 }
188         }
189
190         while (do_it) {
191                 do_it = false;
192
193                 /* expand selection */
194                 mp = me->mpoly;
195                 for (a = 0; a < me->totpoly; a++, mp++) {
196                         if (mp->flag & ME_HIDE)
197                                 continue;
198
199                         if (!BLI_BITMAP_TEST(poly_tag, a)) {
200                                 mark = false;
201
202                                 ml = me->mloop + mp->loopstart;
203                                 for (b = 0; b < mp->totloop; b++, ml++) {
204                                         if ((me->medge[ml->e].flag & ME_SEAM) == 0) {
205                                                 if (BLI_BITMAP_TEST(edge_tag, ml->e)) {
206                                                         mark = true;
207                                                         break;
208                                                 }
209                                         }
210                                 }
211
212                                 if (mark) {
213                                         BLI_BITMAP_ENABLE(poly_tag, a);
214                                         BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
215                                         do_it = true;
216                                 }
217                         }
218                 }
219         }
220
221         MEM_freeN(edge_tag);
222
223         for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) {
224                 if (BLI_BITMAP_TEST(poly_tag, a)) {
225                         SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL);
226                 }
227         }
228
229         MEM_freeN(poly_tag);
230 }
231
232 void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select)
233 {
234         Mesh *me;
235         unsigned int index = (unsigned int)-1;
236
237         me = BKE_mesh_from_object(ob);
238         if (me == NULL || me->totpoly == 0) return;
239
240         if (mval) {
241                 if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
242                         return;
243                 }
244         }
245
246         select_linked_tfaces_with_seams(me, index, select);
247
248         paintface_flush_flags(ob, SELECT);
249 }
250
251 void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
252 {
253         Mesh *me;
254         MPoly *mpoly;
255         int a;
256
257         me = BKE_mesh_from_object(ob);
258         if (me == NULL) return;
259
260         if (action == SEL_TOGGLE) {
261                 action = SEL_SELECT;
262
263                 mpoly = me->mpoly;
264                 a = me->totpoly;
265                 while (a--) {
266                         if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) {
267                                 action = SEL_DESELECT;
268                                 break;
269                         }
270                         mpoly++;
271                 }
272         }
273
274         mpoly = me->mpoly;
275         a = me->totpoly;
276         while (a--) {
277                 if ((mpoly->flag & ME_HIDE) == 0) {
278                         switch (action) {
279                                 case SEL_SELECT:
280                                         mpoly->flag |= ME_FACE_SEL;
281                                         break;
282                                 case SEL_DESELECT:
283                                         mpoly->flag &= ~ME_FACE_SEL;
284                                         break;
285                                 case SEL_INVERT:
286                                         mpoly->flag ^= ME_FACE_SEL;
287                                         break;
288                         }
289                 }
290                 mpoly++;
291         }
292
293         if (flush_flags) {
294                 paintface_flush_flags(ob, SELECT);
295         }
296 }
297
298 bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
299 {
300         const Mesh *me;
301         const MPoly *mp;
302         const MLoop *ml;
303         const MVert *mvert;
304         int a, b;
305         bool ok = false;
306         float vec[3], bmat[3][3];
307
308         me = BKE_mesh_from_object(ob);
309         if (!me || !me->mloopuv) {
310                 return ok;
311         }
312
313         copy_m3_m4(bmat, ob->obmat);
314
315         mvert = me->mvert;
316         mp = me->mpoly;
317         for (a = me->totpoly; a > 0; a--, mp++) {
318                 if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL))
319                         continue;
320
321                 ml = me->mloop + mp->totloop;
322                 for (b = 0; b < mp->totloop; b++, ml++) {
323                         mul_v3_m3v3(vec, bmat, mvert[ml->v].co);
324                         add_v3_v3v3(vec, vec, ob->obmat[3]);
325                         minmax_v3v3_v3(r_min, r_max, vec);
326                 }
327
328                 ok = true;
329         }
330
331         return ok;
332 }
333
334 bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], bool extend, bool deselect, bool toggle)
335 {
336         Mesh *me;
337         MPoly *mpoly, *mpoly_sel;
338         unsigned int a, index;
339
340         /* Get the face under the cursor */
341         me = BKE_mesh_from_object(ob);
342
343         if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
344                 return false;
345
346         if (index >= me->totpoly)
347                 return false;
348
349         mpoly_sel = me->mpoly + index;
350         if (mpoly_sel->flag & ME_HIDE) return false;
351
352         /* clear flags */
353         mpoly = me->mpoly;
354         a = me->totpoly;
355         if (!extend && !deselect && !toggle) {
356                 while (a--) {
357                         mpoly->flag &= ~ME_FACE_SEL;
358                         mpoly++;
359                 }
360         }
361
362         me->act_face = (int)index;
363
364         if (extend) {
365                 mpoly_sel->flag |= ME_FACE_SEL;
366         }
367         else if (deselect) {
368                 mpoly_sel->flag &= ~ME_FACE_SEL;
369         }
370         else if (toggle) {
371                 if (mpoly_sel->flag & ME_FACE_SEL)
372                         mpoly_sel->flag &= ~ME_FACE_SEL;
373                 else
374                         mpoly_sel->flag |= ME_FACE_SEL;
375         }
376         else {
377                 mpoly_sel->flag |= ME_FACE_SEL;
378         }
379
380         /* image window redraw */
381
382         paintface_flush_flags(ob, SELECT);
383         WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
384         ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
385         return true;
386 }
387
388 int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
389 {
390         Object *ob = vc->obact;
391         Mesh *me;
392         MPoly *mpoly;
393         struct ImBuf *ibuf;
394         unsigned int *rt;
395         char *selar;
396         int a, index;
397         const int size[2] = {
398             BLI_rcti_size_x(rect) + 1,
399             BLI_rcti_size_y(rect) + 1};
400
401         me = BKE_mesh_from_object(ob);
402
403         if ((me == NULL) || (me->totpoly == 0) || (size[0] * size[1] <= 0)) {
404                 return OPERATOR_CANCELLED;
405         }
406
407         selar = MEM_callocN(me->totpoly + 1, "selar");
408
409         if (extend == false && select) {
410                 paintface_deselect_all_visible(vc->obact, SEL_DESELECT, false);
411         }
412
413         ED_view3d_backbuf_validate(vc);
414
415         ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
416         rt = ibuf->rect;
417         view3d_opengl_read_pixels(vc->ar, rect->xmin, rect->ymin, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
418         if (ENDIAN_ORDER == B_ENDIAN) {
419                 IMB_convert_rgba_to_abgr(ibuf);
420         }
421         GPU_select_to_index_array(ibuf->rect, size[0] * size[1]);
422
423         a = size[0] * size[1];
424         while (a--) {
425                 if (*rt) {
426                         index = *rt;
427                         if (index <= me->totpoly) {
428                                 selar[index] = 1;
429                         }
430                 }
431                 rt++;
432         }
433
434         mpoly = me->mpoly;
435         for (a = 1; a <= me->totpoly; a++, mpoly++) {
436                 if (selar[a]) {
437                         if (mpoly->flag & ME_HIDE) {
438                                 /* pass */
439                         }
440                         else {
441                                 if (select) mpoly->flag |= ME_FACE_SEL;
442                                 else mpoly->flag &= ~ME_FACE_SEL;
443                         }
444                 }
445         }
446
447         IMB_freeImBuf(ibuf);
448         MEM_freeN(selar);
449
450 #ifdef __APPLE__
451         glReadBuffer(GL_BACK);
452 #endif
453
454         paintface_flush_flags(vc->obact, SELECT);
455
456         return OPERATOR_FINISHED;
457 }
458
459
460 /*  (similar to void paintface_flush_flags(Object *ob))
461  * copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
462  * use in object mode when selecting vertices (while painting) */
463 void paintvert_flush_flags(Object *ob)
464 {
465         Mesh *me = BKE_mesh_from_object(ob);
466         DerivedMesh *dm = ob->derivedFinal;
467         MVert *dm_mvert, *dm_mv;
468         const int *index_array = NULL;
469         int totvert;
470         int i;
471
472         if (me == NULL)
473                 return;
474
475         /* we could call this directly in all areas that change selection,
476          * since this could become slow for realtime updates (circle-select for eg) */
477         BKE_mesh_flush_select_from_verts(me);
478
479         if (dm == NULL)
480                 return;
481
482         index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
483
484         dm_mvert = dm->getVertArray(dm);
485         totvert = dm->getNumVerts(dm);
486
487         dm_mv = dm_mvert;
488
489         if (index_array) {
490                 int orig_index;
491                 for (i = 0; i < totvert; i++, dm_mv++) {
492                         orig_index = index_array[i];
493                         if (orig_index != ORIGINDEX_NONE) {
494                                 dm_mv->flag = me->mvert[index_array[i]].flag;
495                         }
496                 }
497         }
498         else {
499                 for (i = 0; i < totvert; i++, dm_mv++) {
500                         dm_mv->flag = me->mvert[i].flag;
501                 }
502         }
503 }
504 /*  note: if the caller passes false to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */
505 void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
506 {
507         Mesh *me;
508         MVert *mvert;
509         int a;
510
511         me = BKE_mesh_from_object(ob);
512         if (me == NULL) return;
513
514         if (action == SEL_TOGGLE) {
515                 action = SEL_SELECT;
516
517                 mvert = me->mvert;
518                 a = me->totvert;
519                 while (a--) {
520                         if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
521                                 action = SEL_DESELECT;
522                                 break;
523                         }
524                         mvert++;
525                 }
526         }
527
528         mvert = me->mvert;
529         a = me->totvert;
530         while (a--) {
531                 if ((mvert->flag & ME_HIDE) == 0) {
532                         switch (action) {
533                                 case SEL_SELECT:
534                                         mvert->flag |= SELECT;
535                                         break;
536                                 case SEL_DESELECT:
537                                         mvert->flag &= ~SELECT;
538                                         break;
539                                 case SEL_INVERT:
540                                         mvert->flag ^= SELECT;
541                                         break;
542                         }
543                 }
544                 mvert++;
545         }
546
547         /* handle mselect */
548         if (action == SEL_SELECT) {
549                 /* pass */
550         }
551         else if (ELEM(action, SEL_DESELECT, SEL_INVERT)) {
552                 BKE_mesh_mselect_clear(me);
553         }
554         else {
555                 BKE_mesh_mselect_validate(me);
556         }
557
558         if (flush_flags) {
559                 paintvert_flush_flags(ob);
560         }
561 }
562
563 void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
564 {
565         Mesh *me = BKE_mesh_from_object(ob);
566         MVert *mv;
567         MDeformVert *dv;
568         int a, tot;
569
570         if (me == NULL || me->dvert == NULL) {
571                 return;
572         }
573
574         if (!extend) {
575                 paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
576         }
577
578         dv = me->dvert;
579         tot = me->totvert;
580
581         for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) {
582                 if ((mv->flag & ME_HIDE) == 0) {
583                         if (dv->dw == NULL) {
584                                 /* if null weight then not grouped */
585                                 mv->flag |= SELECT;
586                         }
587                 }
588         }
589
590         if (flush_flags) {
591                 paintvert_flush_flags(ob);
592         }
593 }