Blender  V2.93
editface.c
Go to the documentation of this file.
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 
21 #include "MEM_guardedalloc.h"
22 
23 #include "BLI_bitmap.h"
24 #include "BLI_blenlib.h"
25 #include "BLI_math.h"
26 
27 #include "IMB_imbuf.h"
28 #include "IMB_imbuf_types.h"
29 
30 #include "DNA_mesh_types.h"
31 #include "DNA_meshdata_types.h"
32 #include "DNA_object_types.h"
33 
34 #include "BKE_context.h"
35 #include "BKE_customdata.h"
36 #include "BKE_global.h"
37 #include "BKE_mesh.h"
38 #include "BKE_object.h"
39 
40 #include "ED_mesh.h"
41 #include "ED_screen.h"
42 #include "ED_select_utils.h"
43 #include "ED_view3d.h"
44 
45 #include "WM_api.h"
46 #include "WM_types.h"
47 
48 #include "DEG_depsgraph.h"
49 #include "DEG_depsgraph_query.h"
50 
51 /* own include */
52 
53 /* copy the face flags, most importantly selection from the mesh to the final derived mesh,
54  * use in object mode when selecting faces (while painting) */
55 void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
56 {
57  Mesh *me = BKE_mesh_from_object(ob);
58  MPoly *polys, *mp_orig;
59  const int *index_array = NULL;
60  int totpoly;
61 
62  BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
63 
64  if (me == NULL) {
65  return;
66  }
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) {
74  }
75 
78 
79  if (ob_eval == NULL) {
80  return;
81  }
82 
83  Mesh *me_orig = (Mesh *)ob_eval->runtime.data_orig;
84  Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval;
85  bool updated = false;
86 
87  if (me_orig != NULL && me_eval != NULL && me_orig->totpoly == me->totpoly) {
88  /* Update the COW copy of the mesh. */
89  for (int i = 0; i < me->totpoly; i++) {
90  me_orig->mpoly[i].flag = me->mpoly[i].flag;
91  }
92 
93  /* If the mesh has only deform modifiers, the evaluated mesh shares arrays. */
94  if (me_eval->mpoly == me_orig->mpoly) {
95  updated = true;
96  }
97  /* Mesh polys => Final derived polys */
98  else if ((index_array = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
99  polys = me_eval->mpoly;
100  totpoly = me_eval->totpoly;
101 
102  /* loop over final derived polys */
103  for (int i = 0; i < totpoly; i++) {
104  if (index_array[i] != ORIGINDEX_NONE) {
105  /* Copy flags onto the final derived poly from the original mesh poly */
106  mp_orig = me->mpoly + index_array[i];
107  polys[i].flag = mp_orig->flag;
108  }
109  }
110 
111  updated = true;
112  }
113  }
114 
115  if (updated) {
116  if (flag & ME_HIDE) {
118  }
119  else {
121  }
122 
124  }
125  else {
127  }
128 
130 }
131 
132 void paintface_hide(bContext *C, Object *ob, const bool unselected)
133 {
134  Mesh *me;
135  MPoly *mpoly;
136  int a;
137 
138  me = BKE_mesh_from_object(ob);
139  if (me == NULL || me->totpoly == 0) {
140  return;
141  }
142 
143  mpoly = me->mpoly;
144  a = me->totpoly;
145  while (a--) {
146  if ((mpoly->flag & ME_HIDE) == 0) {
147  if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
148  mpoly->flag |= ME_HIDE;
149  }
150  }
151 
152  if (mpoly->flag & ME_HIDE) {
153  mpoly->flag &= ~ME_FACE_SEL;
154  }
155 
156  mpoly++;
157  }
158 
160 
162 }
163 
164 void paintface_reveal(bContext *C, Object *ob, const bool select)
165 {
166  Mesh *me;
167  MPoly *mpoly;
168  int a;
169 
170  me = BKE_mesh_from_object(ob);
171  if (me == NULL || me->totpoly == 0) {
172  return;
173  }
174 
175  mpoly = me->mpoly;
176  a = me->totpoly;
177  while (a--) {
178  if (mpoly->flag & ME_HIDE) {
180  mpoly->flag &= ~ME_HIDE;
181  }
182  mpoly++;
183  }
184 
186 
188 }
189 
190 /* Set tface seams based on edge data, uses hash table to find seam edges. */
191 
192 static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bool select)
193 {
194  MPoly *mp;
195  MLoop *ml;
196  int a, b;
197  bool do_it = true;
198  bool mark = false;
199 
200  BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__);
201  BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__);
202 
203  if (index != (uint)-1) {
204  /* only put face under cursor in array */
205  mp = &me->mpoly[index];
206  BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
207  BLI_BITMAP_ENABLE(poly_tag, index);
208  }
209  else {
210  /* fill array by selection */
211  mp = me->mpoly;
212  for (a = 0; a < me->totpoly; a++, mp++) {
213  if (mp->flag & ME_HIDE) {
214  /* pass */
215  }
216  else if (mp->flag & ME_FACE_SEL) {
217  BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
218  BLI_BITMAP_ENABLE(poly_tag, a);
219  }
220  }
221  }
222 
223  while (do_it) {
224  do_it = false;
225 
226  /* expand selection */
227  mp = me->mpoly;
228  for (a = 0; a < me->totpoly; a++, mp++) {
229  if (mp->flag & ME_HIDE) {
230  continue;
231  }
232 
233  if (!BLI_BITMAP_TEST(poly_tag, a)) {
234  mark = false;
235 
236  ml = me->mloop + mp->loopstart;
237  for (b = 0; b < mp->totloop; b++, ml++) {
238  if ((me->medge[ml->e].flag & ME_SEAM) == 0) {
239  if (BLI_BITMAP_TEST(edge_tag, ml->e)) {
240  mark = true;
241  break;
242  }
243  }
244  }
245 
246  if (mark) {
247  BLI_BITMAP_ENABLE(poly_tag, a);
248  BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
249  do_it = true;
250  }
251  }
252  }
253  }
254 
255  MEM_freeN(edge_tag);
256 
257  for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) {
258  if (BLI_BITMAP_TEST(poly_tag, a)) {
260  }
261  }
262 
263  MEM_freeN(poly_tag);
264 }
265 
266 void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select)
267 {
268  Mesh *me;
269  uint index = (uint)-1;
270 
271  me = BKE_mesh_from_object(ob);
272  if (me == NULL || me->totpoly == 0) {
273  return;
274  }
275 
276  if (mval) {
277  if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
278  return;
279  }
280  }
281 
283 
285 }
286 
287 bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags)
288 {
289  Mesh *me;
290  MPoly *mpoly;
291  int a;
292 
293  me = BKE_mesh_from_object(ob);
294  if (me == NULL) {
295  return false;
296  }
297 
298  if (action == SEL_TOGGLE) {
299  action = SEL_SELECT;
300 
301  mpoly = me->mpoly;
302  a = me->totpoly;
303  while (a--) {
304  if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) {
305  action = SEL_DESELECT;
306  break;
307  }
308  mpoly++;
309  }
310  }
311 
312  bool changed = false;
313 
314  mpoly = me->mpoly;
315  a = me->totpoly;
316  while (a--) {
317  if ((mpoly->flag & ME_HIDE) == 0) {
318  switch (action) {
319  case SEL_SELECT:
320  if ((mpoly->flag & ME_FACE_SEL) == 0) {
321  mpoly->flag |= ME_FACE_SEL;
322  changed = true;
323  }
324  break;
325  case SEL_DESELECT:
326  if ((mpoly->flag & ME_FACE_SEL) != 0) {
327  mpoly->flag &= ~ME_FACE_SEL;
328  changed = true;
329  }
330  break;
331  case SEL_INVERT:
332  mpoly->flag ^= ME_FACE_SEL;
333  changed = true;
334  break;
335  }
336  }
337  mpoly++;
338  }
339 
340  if (changed) {
341  if (flush_flags) {
343  }
344  }
345  return changed;
346 }
347 
348 bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
349 {
350  const Mesh *me;
351  const MPoly *mp;
352  const MLoop *ml;
353  const MVert *mvert;
354  int a, b;
355  bool ok = false;
356  float vec[3], bmat[3][3];
357 
358  me = BKE_mesh_from_object(ob);
359  if (!me || !me->mloopuv) {
360  return ok;
361  }
362 
363  copy_m3_m4(bmat, ob->obmat);
364 
365  mvert = me->mvert;
366  mp = me->mpoly;
367  for (a = me->totpoly; a > 0; a--, mp++) {
368  if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL)) {
369  continue;
370  }
371 
372  ml = me->mloop + mp->loopstart;
373  for (b = 0; b < mp->totloop; b++, ml++) {
374  mul_v3_m3v3(vec, bmat, mvert[ml->v].co);
375  add_v3_v3v3(vec, vec, ob->obmat[3]);
376  minmax_v3v3_v3(r_min, r_max, vec);
377  }
378 
379  ok = true;
380  }
381 
382  return ok;
383 }
384 
386  struct bContext *C, Object *ob, const int mval[2], bool extend, bool deselect, bool toggle)
387 {
388  Mesh *me;
389  MPoly *mpoly_sel;
390  uint index;
391 
392  /* Get the face under the cursor */
393  me = BKE_mesh_from_object(ob);
394 
395  if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
396  return false;
397  }
398 
399  if (index >= me->totpoly) {
400  return false;
401  }
402 
403  mpoly_sel = me->mpoly + index;
404  if (mpoly_sel->flag & ME_HIDE) {
405  return false;
406  }
407 
408  /* clear flags */
409  if (!extend && !deselect && !toggle) {
411  }
412 
413  me->act_face = (int)index;
414 
415  if (extend) {
416  mpoly_sel->flag |= ME_FACE_SEL;
417  }
418  else if (deselect) {
419  mpoly_sel->flag &= ~ME_FACE_SEL;
420  }
421  else if (toggle) {
422  if (mpoly_sel->flag & ME_FACE_SEL) {
423  mpoly_sel->flag &= ~ME_FACE_SEL;
424  }
425  else {
426  mpoly_sel->flag |= ME_FACE_SEL;
427  }
428  }
429  else {
430  mpoly_sel->flag |= ME_FACE_SEL;
431  }
432 
433  /* image window redraw */
434 
436  ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
437  return true;
438 }
439 
440 /* (similar to void paintface_flush_flags(Object *ob))
441  * copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
442  * use in object mode when selecting vertices (while painting) */
444 {
445  Mesh *me = BKE_mesh_from_object(ob);
446  Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
447  MVert *mvert_eval, *mv;
448  const int *index_array = NULL;
449  int totvert;
450  int i;
451 
452  if (me == NULL) {
453  return;
454  }
455 
456  /* we could call this directly in all areas that change selection,
457  * since this could become slow for realtime updates (circle-select for eg) */
459 
460  if (me_eval == NULL) {
461  return;
462  }
463 
464  index_array = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
465 
466  mvert_eval = me_eval->mvert;
467  totvert = me_eval->totvert;
468 
469  mv = mvert_eval;
470 
471  if (index_array) {
472  int orig_index;
473  for (i = 0; i < totvert; i++, mv++) {
474  orig_index = index_array[i];
475  if (orig_index != ORIGINDEX_NONE) {
476  mv->flag = me->mvert[index_array[i]].flag;
477  }
478  }
479  }
480  else {
481  for (i = 0; i < totvert; i++, mv++) {
482  mv->flag = me->mvert[i].flag;
483  }
484  }
485 
487 }
488 
489 void paintvert_tag_select_update(struct bContext *C, struct Object *ob)
490 {
493 }
494 
499 bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
500 {
501  Mesh *me;
502  MVert *mvert;
503  int a;
504 
505  me = BKE_mesh_from_object(ob);
506  if (me == NULL) {
507  return false;
508  }
509 
510  if (action == SEL_TOGGLE) {
511  action = SEL_SELECT;
512 
513  mvert = me->mvert;
514  a = me->totvert;
515  while (a--) {
516  if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
517  action = SEL_DESELECT;
518  break;
519  }
520  mvert++;
521  }
522  }
523 
524  bool changed = false;
525  mvert = me->mvert;
526  a = me->totvert;
527  while (a--) {
528  if ((mvert->flag & ME_HIDE) == 0) {
529  switch (action) {
530  case SEL_SELECT:
531  if ((mvert->flag & SELECT) == 0) {
532  mvert->flag |= SELECT;
533  changed = true;
534  }
535  break;
536  case SEL_DESELECT:
537  if ((mvert->flag & SELECT) != 0) {
538  mvert->flag &= ~SELECT;
539  changed = true;
540  }
541  break;
542  case SEL_INVERT:
543  mvert->flag ^= SELECT;
544  changed = true;
545  break;
546  }
547  }
548  mvert++;
549  }
550 
551  if (changed) {
552  /* handle mselect */
553  if (action == SEL_SELECT) {
554  /* pass */
555  }
556  else if (ELEM(action, SEL_DESELECT, SEL_INVERT)) {
558  }
559  else {
561  }
562 
563  if (flush_flags) {
565  }
566  }
567  return changed;
568 }
569 
570 void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
571 {
572  Mesh *me = BKE_mesh_from_object(ob);
573  MVert *mv;
574  MDeformVert *dv;
575  int a, tot;
576 
577  if (me == NULL || me->dvert == NULL) {
578  return;
579  }
580 
581  if (!extend) {
583  }
584 
585  dv = me->dvert;
586  tot = me->totvert;
587 
588  for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) {
589  if ((mv->flag & ME_HIDE) == 0) {
590  if (dv->dw == NULL) {
591  /* if null weight then not grouped */
592  mv->flag |= SELECT;
593  }
594  }
595  }
596 
597  if (flush_flags) {
599  }
600 }
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
CustomData interface, see also DNA_customdata_types.h.
#define ORIGINDEX_NONE
void * CustomData_get_layer(const struct CustomData *data, int type)
void BKE_mesh_flush_select_from_verts(struct Mesh *me)
void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap, const struct MPoly *mp, const struct MLoop *mloop)
struct Mesh * BKE_mesh_from_object(struct Object *ob)
Definition: mesh.c:1271
void BKE_mesh_mselect_validate(struct Mesh *me)
Definition: mesh.c:1617
void BKE_mesh_batch_cache_dirty_tag(struct Mesh *me, eMeshBatchDirtyMode mode)
Definition: mesh_runtime.c:251
void BKE_mesh_flush_select_from_polys(struct Mesh *me)
void BKE_mesh_mselect_clear(struct Mesh *me)
Definition: mesh.c:1608
void BKE_mesh_flush_hidden_from_polys(struct Mesh *me)
@ BKE_MESH_BATCH_DIRTY_SELECT_PAINT
@ BKE_MESH_BATCH_DIRTY_ALL
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_evaluated_mesh(struct Object *object)
Definition: object.c:4459
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
unsigned int uint
Definition: BLI_sys_types.h:83
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
@ CD_ORIGINDEX
@ ME_HIDE
@ ME_SEAM
@ ME_FACE_SEL
Object is a sort of wrapper for general info.
bool ED_mesh_pick_face(struct bContext *C, struct Object *ob, const int mval[2], uint dist_px, uint *r_index)
Definition: meshtools.c:1215
#define ED_MESH_PICK_DEFAULT_FACE_DIST
Definition: ED_mesh.h:515
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:667
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
#define NC_GEOM
Definition: WM_types.h:294
#define ND_SELECT
Definition: WM_types.h:407
#define SELECT
const Depsgraph * depsgraph
bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], bool extend, bool deselect, bool toggle)
Definition: editface.c:385
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
Definition: editface.c:348
void paintvert_flush_flags(Object *ob)
Definition: editface.c:443
void paintface_reveal(bContext *C, Object *ob, const bool select)
Definition: editface.c:164
void paintface_hide(bContext *C, Object *ob, const bool unselected)
Definition: editface.c:132
void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
Definition: editface.c:570
bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
Definition: editface.c:499
void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
Definition: editface.c:55
bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags)
Definition: editface.c:287
static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bool select)
Definition: editface.c:192
void paintvert_tag_select_update(struct bContext *C, struct Object *ob)
Definition: editface.c:489
void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select)
Definition: editface.c:266
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static unsigned a[3]
Definition: RandGen.cpp:92
struct MDeformWeight * dw
unsigned int e
unsigned int v
float co[3]
struct MEdge * medge
struct MVert * mvert
struct MDeformVert * dvert
int totedge
struct MLoopUV * mloopuv
int act_face
int totvert
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
struct ID * data_eval
struct ID * data_orig
Object_Runtime runtime
float obmat[4][4]
void * data
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: util_avxb.h:167
void WM_event_add_notifier(const bContext *C, uint type, void *reference)