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 * The Original Code is Copyright (C) 2004 by Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup edmesh
22 */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "DNA_key_types.h"
27 #include "DNA_mesh_types.h"
28 #include "DNA_object_types.h"
29
30 #include "BLI_alloca.h"
31 #include "BLI_buffer.h"
32 #include "BLI_kdtree.h"
33 #include "BLI_listbase.h"
34 #include "BLI_math.h"
35
36 #include "BKE_DerivedMesh.h"
37 #include "BKE_context.h"
38 #include "BKE_editmesh.h"
39 #include "BKE_editmesh_bvh.h"
40 #include "BKE_global.h"
41 #include "BKE_layer.h"
42 #include "BKE_main.h"
43 #include "BKE_mesh.h"
44 #include "BKE_mesh_mapping.h"
45 #include "BKE_report.h"
46
47 #include "DEG_depsgraph.h"
48
49 #include "BKE_object.h" /* XXX. only for EDBM_mesh_load(). */
50
51 #include "WM_api.h"
52 #include "WM_types.h"
53
54 #include "ED_mesh.h"
55 #include "ED_screen.h"
56 #include "ED_transform_snap_object_context.h"
57 #include "ED_uvedit.h"
58 #include "ED_view3d.h"
59
60 #include "mesh_intern.h" /* own include */
61
62 /* -------------------------------------------------------------------- */
63 /** \name Redo API
64 * \{ */
65
66 /* Mesh backup implementation.
67 * This would greatly benefit from some sort of binary diffing
68 * just as the undo stack would.
69 * So leaving this as an interface for further work */
70
EDBM_redo_state_store(BMEditMesh * em)71 BMBackup EDBM_redo_state_store(BMEditMesh *em)
72 {
73 BMBackup backup;
74 backup.bmcopy = BM_mesh_copy(em->bm);
75 return backup;
76 }
77
EDBM_redo_state_restore(BMBackup backup,BMEditMesh * em,int recalctess)78 void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess)
79 {
80 BMesh *tmpbm;
81 if (!em || !backup.bmcopy) {
82 return;
83 }
84
85 BM_mesh_data_free(em->bm);
86 tmpbm = BM_mesh_copy(backup.bmcopy);
87 *em->bm = *tmpbm;
88 MEM_freeN(tmpbm);
89 tmpbm = NULL;
90
91 if (recalctess) {
92 BKE_editmesh_looptri_calc(em);
93 }
94 }
95
EDBM_redo_state_free(BMBackup * backup,BMEditMesh * em,int recalctess)96 void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
97 {
98 if (em && backup->bmcopy) {
99 BM_mesh_data_free(em->bm);
100 *em->bm = *backup->bmcopy;
101 }
102 else if (backup->bmcopy) {
103 BM_mesh_data_free(backup->bmcopy);
104 }
105
106 if (backup->bmcopy) {
107 MEM_freeN(backup->bmcopy);
108 }
109 backup->bmcopy = NULL;
110
111 if (recalctess && em) {
112 BKE_editmesh_looptri_calc(em);
113 }
114 }
115
116 /** \} */
117
118 /* -------------------------------------------------------------------- */
119 /** \name BMesh Operator (BMO) API Wrapper
120 * \{ */
121
EDBM_op_init(BMEditMesh * em,BMOperator * bmop,wmOperator * op,const char * fmt,...)122 bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...)
123 {
124 BMesh *bm = em->bm;
125 va_list list;
126
127 va_start(list, fmt);
128
129 if (!BMO_op_vinitf(bm, bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
130 BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
131 va_end(list);
132 return false;
133 }
134
135 if (!em->emcopy) {
136 em->emcopy = BKE_editmesh_copy(em);
137 }
138 em->emcopyusers++;
139
140 va_end(list);
141
142 return true;
143 }
144
145 /* returns 0 on error, 1 on success. executes and finishes a bmesh operator */
EDBM_op_finish(BMEditMesh * em,BMOperator * bmop,wmOperator * op,const bool do_report)146 bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report)
147 {
148 const char *errmsg;
149
150 BMO_op_finish(em->bm, bmop);
151
152 if (BMO_error_get(em->bm, &errmsg, NULL)) {
153 BMEditMesh *emcopy = em->emcopy;
154
155 if (do_report) {
156 BKE_report(op->reports, RPT_ERROR, errmsg);
157 }
158
159 EDBM_mesh_free(em);
160 *em = *emcopy;
161
162 MEM_freeN(emcopy);
163 em->emcopyusers = 0;
164 em->emcopy = NULL;
165
166 /**
167 * Note, we could pass in the mesh, however this is an exceptional case, allow a slow lookup.
168 *
169 * This is needed because the COW mesh makes a full copy of the #BMEditMesh
170 * instead of sharing the pointer, tagging since this has been freed above,
171 * the #BMEditMesh.emcopy needs to be flushed to the COW edit-mesh, see T55457.
172 */
173 {
174 Main *bmain = G_MAIN;
175 for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) {
176 if (mesh->edit_mesh == em) {
177 DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE);
178 break;
179 }
180 }
181 }
182
183 /* when copying, tessellation isn't to for faster copying,
184 * but means we need to re-tessellate here */
185 if (em->looptris == NULL) {
186 BKE_editmesh_looptri_calc(em);
187 }
188
189 return false;
190 }
191
192 em->emcopyusers--;
193 if (em->emcopyusers < 0) {
194 printf("warning: em->emcopyusers was less than zero.\n");
195 }
196
197 if (em->emcopyusers <= 0) {
198 BKE_editmesh_free(em->emcopy);
199 MEM_freeN(em->emcopy);
200 em->emcopy = NULL;
201 }
202
203 return true;
204 }
205
EDBM_op_callf(BMEditMesh * em,wmOperator * op,const char * fmt,...)206 bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
207 {
208 BMesh *bm = em->bm;
209 BMOperator bmop;
210 va_list list;
211
212 va_start(list, fmt);
213
214 if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
215 BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
216 va_end(list);
217 return false;
218 }
219
220 if (!em->emcopy) {
221 em->emcopy = BKE_editmesh_copy(em);
222 }
223 em->emcopyusers++;
224
225 BMO_op_exec(bm, &bmop);
226
227 va_end(list);
228 return EDBM_op_finish(em, &bmop, op, true);
229 }
230
EDBM_op_call_and_selectf(BMEditMesh * em,wmOperator * op,const char * select_slot_out,const bool select_extend,const char * fmt,...)231 bool EDBM_op_call_and_selectf(BMEditMesh *em,
232 wmOperator *op,
233 const char *select_slot_out,
234 const bool select_extend,
235 const char *fmt,
236 ...)
237 {
238 BMOpSlot *slot_select_out;
239 BMesh *bm = em->bm;
240 BMOperator bmop;
241 va_list list;
242 char hflag;
243
244 va_start(list, fmt);
245
246 if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
247 BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
248 va_end(list);
249 return false;
250 }
251
252 if (!em->emcopy) {
253 em->emcopy = BKE_editmesh_copy(em);
254 }
255 em->emcopyusers++;
256
257 BMO_op_exec(bm, &bmop);
258
259 slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out);
260 hflag = slot_select_out->slot_subtype.elem & BM_ALL_NOLOOP;
261 BLI_assert(hflag != 0);
262
263 if (select_extend == false) {
264 BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
265 }
266
267 BMO_slot_buffer_hflag_enable(
268 em->bm, bmop.slots_out, select_slot_out, hflag, BM_ELEM_SELECT, true);
269
270 va_end(list);
271 return EDBM_op_finish(em, &bmop, op, true);
272 }
273
EDBM_op_call_silentf(BMEditMesh * em,const char * fmt,...)274 bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
275 {
276 BMesh *bm = em->bm;
277 BMOperator bmop;
278 va_list list;
279
280 va_start(list, fmt);
281
282 if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
283 va_end(list);
284 return false;
285 }
286
287 if (!em->emcopy) {
288 em->emcopy = BKE_editmesh_copy(em);
289 }
290 em->emcopyusers++;
291
292 BMO_op_exec(bm, &bmop);
293
294 va_end(list);
295 return EDBM_op_finish(em, &bmop, NULL, false);
296 }
297
298 /** \} */
299
300 /* -------------------------------------------------------------------- */
301 /** \name Edit BMesh API
302 *
303 * Make/Clear/Free functions.
304 * \{ */
305
EDBM_mesh_make(Object * ob,const int select_mode,const bool add_key_index)306 void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
307 {
308 Mesh *me = ob->data;
309 BMesh *bm;
310
311 bm = BKE_mesh_to_bmesh(me,
312 ob,
313 add_key_index,
314 &((struct BMeshCreateParams){
315 .use_toolflags = true,
316 }));
317
318 if (me->edit_mesh) {
319 /* this happens when switching shape keys */
320 EDBM_mesh_free(me->edit_mesh);
321 MEM_freeN(me->edit_mesh);
322 }
323
324 /* currently executing operators re-tessellates, so we can avoid doing here
325 * but at some point it may need to be added back. */
326 #if 0
327 me->edit_mesh = BKE_editmesh_create(bm, true);
328 #else
329 me->edit_mesh = BKE_editmesh_create(bm, false);
330 #endif
331
332 me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode;
333 me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0;
334
335 /* we need to flush selection because the mode may have changed from when last in editmode */
336 EDBM_selectmode_flush(me->edit_mesh);
337 }
338
339 /**
340 * \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates).
341 * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913
342 */
EDBM_mesh_load_ex(Main * bmain,Object * ob,bool free_data)343 void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
344 {
345 Mesh *me = ob->data;
346 BMesh *bm = me->edit_mesh->bm;
347
348 /* Workaround for T42360, 'ob->shapenr' should be 1 in this case.
349 * however this isn't synchronized between objects at the moment. */
350 if (UNLIKELY((ob->shapenr == 0) && (me->key && !BLI_listbase_is_empty(&me->key->block)))) {
351 bm->shapenr = 1;
352 }
353
354 BM_mesh_bm_to_me(bmain,
355 bm,
356 me,
357 (&(struct BMeshToMeshParams){
358 .calc_object_remap = true,
359 .update_shapekey_indices = !free_data,
360 }));
361
362 /* Free derived mesh. usually this would happen through depsgraph but there
363 * are exceptions like file save that will not cause this, and we want to
364 * avoid ending up with an invalid derived mesh then.
365 *
366 * Do it for all objects which shares the same mesh datablock, since their
367 * derived meshes might also be referencing data which was just freed,
368 *
369 * Annoying enough, but currently seems most efficient way to avoid access
370 * of freed data on scene update, especially in cases when there are dependency
371 * cycles.
372 */
373 #if 0
374 for (Object *other_object = bmain->objects.first; other_object != NULL; other_object = other_object->id.next) {
375 if (other_object->data == ob->data) {
376 BKE_object_free_derived_caches(other_object);
377 }
378 }
379 #endif
380 }
381
EDBM_mesh_clear(BMEditMesh * em)382 void EDBM_mesh_clear(BMEditMesh *em)
383 {
384 /* clear bmesh */
385 BM_mesh_clear(em->bm);
386
387 /* free derived meshes */
388 BKE_editmesh_free_derivedmesh(em);
389
390 /* free tessellation data */
391 em->tottri = 0;
392 if (em->looptris) {
393 MEM_freeN(em->looptris);
394 em->looptris = NULL;
395 }
396 }
397
EDBM_mesh_load(Main * bmain,Object * ob)398 void EDBM_mesh_load(Main *bmain, Object *ob)
399 {
400 EDBM_mesh_load_ex(bmain, ob, true);
401 }
402
403 /**
404 * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free
405 */
EDBM_mesh_free(BMEditMesh * em)406 void EDBM_mesh_free(BMEditMesh *em)
407 {
408 /* These tables aren't used yet, so it's not strictly necessary
409 * to 'end' them but if someone tries to start using them,
410 * having these in place will save a lot of pain. */
411 ED_mesh_mirror_spatial_table_end(NULL);
412 ED_mesh_mirror_topo_table_end(NULL);
413
414 BKE_editmesh_free(em);
415 }
416
417 /** \} */
418
419 /* -------------------------------------------------------------------- */
420 /** \name Selection Utilities
421 * \{ */
422
EDBM_selectmode_to_scene(bContext * C)423 void EDBM_selectmode_to_scene(bContext *C)
424 {
425 Scene *scene = CTX_data_scene(C);
426 Object *obedit = CTX_data_edit_object(C);
427 BMEditMesh *em = BKE_editmesh_from_object(obedit);
428
429 if (!em) {
430 return;
431 }
432
433 scene->toolsettings->selectmode = em->selectmode;
434
435 /* Request redraw of header buttons (to show new select mode) */
436 WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
437 }
438
EDBM_selectmode_flush_ex(BMEditMesh * em,const short selectmode)439 void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode)
440 {
441 BM_mesh_select_mode_flush_ex(em->bm, selectmode);
442 }
443
EDBM_selectmode_flush(BMEditMesh * em)444 void EDBM_selectmode_flush(BMEditMesh *em)
445 {
446 EDBM_selectmode_flush_ex(em, em->selectmode);
447 }
448
EDBM_deselect_flush(BMEditMesh * em)449 void EDBM_deselect_flush(BMEditMesh *em)
450 {
451 /* function below doesn't use. just do this to keep the values in sync */
452 em->bm->selectmode = em->selectmode;
453 BM_mesh_deselect_flush(em->bm);
454 }
455
EDBM_select_flush(BMEditMesh * em)456 void EDBM_select_flush(BMEditMesh *em)
457 {
458 /* function below doesn't use. just do this to keep the values in sync */
459 em->bm->selectmode = em->selectmode;
460 BM_mesh_select_flush(em->bm);
461 }
462
EDBM_select_more(BMEditMesh * em,const bool use_face_step)463 void EDBM_select_more(BMEditMesh *em, const bool use_face_step)
464 {
465 BMOperator bmop;
466 const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
467
468 BMO_op_initf(em->bm,
469 &bmop,
470 BMO_FLAG_DEFAULTS,
471 "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
472 BM_ELEM_SELECT,
473 false,
474 use_faces,
475 use_face_step);
476 BMO_op_exec(em->bm, &bmop);
477 /* don't flush selection in edge/vertex mode */
478 BMO_slot_buffer_hflag_enable(
479 em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
480 BMO_op_finish(em->bm, &bmop);
481
482 EDBM_selectmode_flush(em);
483 }
484
EDBM_select_less(BMEditMesh * em,const bool use_face_step)485 void EDBM_select_less(BMEditMesh *em, const bool use_face_step)
486 {
487 BMOperator bmop;
488 const bool use_faces = (em->selectmode == SCE_SELECT_FACE);
489
490 BMO_op_initf(em->bm,
491 &bmop,
492 BMO_FLAG_DEFAULTS,
493 "region_extend geom=%hvef use_contract=%b use_faces=%b use_face_step=%b",
494 BM_ELEM_SELECT,
495 true,
496 use_faces,
497 use_face_step);
498 BMO_op_exec(em->bm, &bmop);
499 /* don't flush selection in edge/vertex mode */
500 BMO_slot_buffer_hflag_disable(
501 em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
502 BMO_op_finish(em->bm, &bmop);
503
504 EDBM_selectmode_flush(em);
505
506 /* only needed for select less, ensure we don't have isolated elements remaining */
507 BM_mesh_select_mode_clean(em->bm);
508 }
509
EDBM_flag_disable_all(BMEditMesh * em,const char hflag)510 void EDBM_flag_disable_all(BMEditMesh *em, const char hflag)
511 {
512 BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, false);
513 }
514
EDBM_flag_enable_all(BMEditMesh * em,const char hflag)515 void EDBM_flag_enable_all(BMEditMesh *em, const char hflag)
516 {
517 BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, true);
518 }
519
520 /** \} */
521
522 /* -------------------------------------------------------------------- */
523 /** \name UV Vertex Map API
524 * \{ */
525
526 /**
527 * Return a new #UvVertMap from the edit-mesh.
528 */
BM_uv_vert_map_create(BMesh * bm,const bool use_select,const bool use_winding)529 UvVertMap *BM_uv_vert_map_create(BMesh *bm, const bool use_select, const bool use_winding)
530 {
531 BMVert *ev;
532 BMFace *efa;
533 BMLoop *l;
534 BMIter iter, liter;
535 /* vars from original func */
536 UvVertMap *vmap;
537 UvMapVert *buf;
538 const MLoopUV *luv;
539 uint a;
540 int totverts, i, totuv, totfaces;
541 const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
542 bool *winding = NULL;
543 BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
544
545 BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
546
547 totfaces = bm->totface;
548 totverts = bm->totvert;
549 totuv = 0;
550
551 /* generate UvMapVert array */
552 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
553 if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
554 totuv += efa->len;
555 }
556 }
557
558 if (totuv == 0) {
559 return NULL;
560 }
561 vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
562 if (!vmap) {
563 return NULL;
564 }
565
566 vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totverts, "UvMapVert_pt");
567 buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * totuv, "UvMapVert");
568 if (use_winding) {
569 winding = MEM_callocN(sizeof(*winding) * totfaces, "winding");
570 }
571
572 if (!vmap->vert || !vmap->buf) {
573 BKE_mesh_uv_vert_map_free(vmap);
574 return NULL;
575 }
576
577 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, a) {
578 if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
579 float(*tf_uv)[2] = NULL;
580
581 if (use_winding) {
582 tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
583 }
584
585 BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
586 buf->loop_of_poly_index = i;
587 buf->poly_index = a;
588 buf->separate = 0;
589
590 buf->next = vmap->vert[BM_elem_index_get(l->v)];
591 vmap->vert[BM_elem_index_get(l->v)] = buf;
592 buf++;
593
594 if (use_winding) {
595 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
596 copy_v2_v2(tf_uv[i], luv->uv);
597 }
598 }
599
600 if (use_winding) {
601 winding[a] = cross_poly_v2(tf_uv, efa->len) > 0;
602 }
603 }
604 }
605
606 /* sort individual uvs for each vert */
607 BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) {
608 UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
609 UvMapVert *iterv, *v, *lastv, *next;
610 const float *uv, *uv2;
611
612 while (vlist) {
613 v = vlist;
614 vlist = vlist->next;
615 v->next = newvlist;
616 newvlist = v;
617
618 efa = BM_face_at_index(bm, v->poly_index);
619
620 l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->loop_of_poly_index);
621 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
622 uv = luv->uv;
623
624 lastv = NULL;
625 iterv = vlist;
626
627 while (iterv) {
628 next = iterv->next;
629 efa = BM_face_at_index(bm, iterv->poly_index);
630 l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->loop_of_poly_index);
631 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
632 uv2 = luv->uv;
633
634 if (compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT) &&
635 (!use_winding || winding[iterv->poly_index] == winding[v->poly_index])) {
636 if (lastv) {
637 lastv->next = next;
638 }
639 else {
640 vlist = next;
641 }
642 iterv->next = newvlist;
643 newvlist = iterv;
644 }
645 else {
646 lastv = iterv;
647 }
648
649 iterv = next;
650 }
651
652 newvlist->separate = 1;
653 }
654
655 vmap->vert[a] = newvlist;
656 }
657
658 if (use_winding) {
659 MEM_freeN(winding);
660 }
661
662 BLI_buffer_free(&tf_uv_buf);
663
664 return vmap;
665 }
666
BM_uv_vert_map_at_index(UvVertMap * vmap,uint v)667 UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, uint v)
668 {
669 return vmap->vert[v];
670 }
671
672 /* A specialized vert map used by stitch operator */
BM_uv_element_map_create(BMesh * bm,const Scene * scene,const bool face_selected,const bool uv_selected,const bool use_winding,const bool do_islands)673 UvElementMap *BM_uv_element_map_create(BMesh *bm,
674 const Scene *scene,
675 const bool face_selected,
676 const bool uv_selected,
677 const bool use_winding,
678 const bool do_islands)
679 {
680 BMVert *ev;
681 BMFace *efa;
682 BMLoop *l;
683 BMIter iter, liter;
684 /* vars from original func */
685 UvElementMap *element_map;
686 UvElement *buf;
687 bool *winding = NULL;
688 BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
689
690 MLoopUV *luv;
691 int totverts, totfaces, i, totuv, j;
692
693 const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
694
695 BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
696
697 totfaces = bm->totface;
698 totverts = bm->totvert;
699 totuv = 0;
700
701 /* generate UvElement array */
702 BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
703 if (!face_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
704 if (!uv_selected) {
705 totuv += efa->len;
706 }
707 else {
708 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
709 if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
710 totuv++;
711 }
712 }
713 }
714 }
715 }
716
717 if (totuv == 0) {
718 return NULL;
719 }
720
721 element_map = (UvElementMap *)MEM_callocN(sizeof(*element_map), "UvElementMap");
722 element_map->totalUVs = totuv;
723 element_map->vert = (UvElement **)MEM_callocN(sizeof(*element_map->vert) * totverts,
724 "UvElementVerts");
725 buf = element_map->buf = (UvElement *)MEM_callocN(sizeof(*element_map->buf) * totuv,
726 "UvElement");
727
728 if (use_winding) {
729 winding = MEM_mallocN(sizeof(*winding) * totfaces, "winding");
730 }
731
732 BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, j) {
733
734 if (use_winding) {
735 winding[j] = false;
736 }
737
738 if (!face_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
739 float(*tf_uv)[2] = NULL;
740
741 if (use_winding) {
742 tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
743 }
744
745 BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
746 if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
747 continue;
748 }
749
750 buf->l = l;
751 buf->separate = 0;
752 buf->island = INVALID_ISLAND;
753 buf->loop_of_poly_index = i;
754
755 buf->next = element_map->vert[BM_elem_index_get(l->v)];
756 element_map->vert[BM_elem_index_get(l->v)] = buf;
757
758 if (use_winding) {
759 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
760 copy_v2_v2(tf_uv[i], luv->uv);
761 }
762
763 buf++;
764 }
765
766 if (use_winding) {
767 winding[j] = cross_poly_v2(tf_uv, efa->len) > 0;
768 }
769 }
770 }
771
772 /* sort individual uvs for each vert */
773 BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, i) {
774 UvElement *newvlist = NULL, *vlist = element_map->vert[i];
775 UvElement *iterv, *v, *lastv, *next;
776 const float *uv, *uv2;
777 bool uv_vert_sel, uv2_vert_sel;
778
779 while (vlist) {
780 v = vlist;
781 vlist = vlist->next;
782 v->next = newvlist;
783 newvlist = v;
784
785 l = v->l;
786 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
787 uv = luv->uv;
788 uv_vert_sel = luv->flag & MLOOPUV_VERTSEL;
789
790 lastv = NULL;
791 iterv = vlist;
792
793 while (iterv) {
794 next = iterv->next;
795
796 l = iterv->l;
797 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
798 uv2 = luv->uv;
799 uv2_vert_sel = luv->flag & MLOOPUV_VERTSEL;
800
801 /* Check if the uv loops share the same selection state (if not, they are not connected as
802 * they have been ripped or other edit commands have separated them). */
803 const bool connected = (uv_vert_sel == uv2_vert_sel) &&
804 compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT);
805
806 if (connected && (!use_winding || winding[BM_elem_index_get(iterv->l->f)] ==
807 winding[BM_elem_index_get(v->l->f)])) {
808 if (lastv) {
809 lastv->next = next;
810 }
811 else {
812 vlist = next;
813 }
814 iterv->next = newvlist;
815 newvlist = iterv;
816 }
817 else {
818 lastv = iterv;
819 }
820
821 iterv = next;
822 }
823
824 newvlist->separate = 1;
825 }
826
827 element_map->vert[i] = newvlist;
828 }
829
830 if (use_winding) {
831 MEM_freeN(winding);
832 }
833
834 if (do_islands) {
835 uint *map;
836 BMFace **stack;
837 int stacksize = 0;
838 UvElement *islandbuf;
839 /* island number for faces */
840 int *island_number = NULL;
841
842 int nislands = 0, islandbufsize = 0;
843
844 /* map holds the map from current vmap->buf to the new, sorted map */
845 map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap");
846 stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack");
847 islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer");
848 island_number = MEM_mallocN(sizeof(*island_number) * totfaces, "uv_island_number_face");
849 copy_vn_i(island_number, totfaces, INVALID_ISLAND);
850
851 /* at this point, every UvElement in vert points to a UvElement sharing the same vertex.
852 * Now we should sort uv's in islands. */
853 for (i = 0; i < totuv; i++) {
854 if (element_map->buf[i].island == INVALID_ISLAND) {
855 element_map->buf[i].island = nislands;
856 stack[0] = element_map->buf[i].l->f;
857 island_number[BM_elem_index_get(stack[0])] = nislands;
858 stacksize = 1;
859
860 while (stacksize > 0) {
861 efa = stack[--stacksize];
862
863 BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
864 if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
865 continue;
866 }
867
868 UvElement *element, *initelement = element_map->vert[BM_elem_index_get(l->v)];
869
870 for (element = initelement; element; element = element->next) {
871 if (element->separate) {
872 initelement = element;
873 }
874
875 if (element->l->f == efa) {
876 /* found the uv corresponding to our face and vertex.
877 * Now fill it to the buffer */
878 element->island = nislands;
879 map[element - element_map->buf] = islandbufsize;
880 islandbuf[islandbufsize].l = element->l;
881 islandbuf[islandbufsize].separate = element->separate;
882 islandbuf[islandbufsize].loop_of_poly_index = element->loop_of_poly_index;
883 islandbuf[islandbufsize].island = nislands;
884 islandbufsize++;
885
886 for (element = initelement; element; element = element->next) {
887 if (element->separate && element != initelement) {
888 break;
889 }
890
891 if (island_number[BM_elem_index_get(element->l->f)] == INVALID_ISLAND) {
892 stack[stacksize++] = element->l->f;
893 island_number[BM_elem_index_get(element->l->f)] = nislands;
894 }
895 }
896 break;
897 }
898 }
899 }
900 }
901
902 nislands++;
903 }
904 }
905
906 MEM_freeN(island_number);
907
908 /* remap */
909 for (i = 0; i < bm->totvert; i++) {
910 /* important since we may do selection only. Some of these may be NULL */
911 if (element_map->vert[i]) {
912 element_map->vert[i] = &islandbuf[map[element_map->vert[i] - element_map->buf]];
913 }
914 }
915
916 element_map->islandIndices = MEM_callocN(sizeof(*element_map->islandIndices) * nislands,
917 "UvElementMap_island_indices");
918 j = 0;
919 for (i = 0; i < totuv; i++) {
920 UvElement *element = element_map->buf[i].next;
921 if (element == NULL) {
922 islandbuf[map[i]].next = NULL;
923 }
924 else {
925 islandbuf[map[i]].next = &islandbuf[map[element - element_map->buf]];
926 }
927
928 if (islandbuf[i].island != j) {
929 j++;
930 element_map->islandIndices[j] = i;
931 }
932 }
933
934 MEM_freeN(element_map->buf);
935
936 element_map->buf = islandbuf;
937 element_map->totalIslands = nislands;
938 MEM_freeN(stack);
939 MEM_freeN(map);
940 }
941
942 BLI_buffer_free(&tf_uv_buf);
943
944 return element_map;
945 }
946
BM_uv_vert_map_free(UvVertMap * vmap)947 void BM_uv_vert_map_free(UvVertMap *vmap)
948 {
949 if (vmap) {
950 if (vmap->vert) {
951 MEM_freeN(vmap->vert);
952 }
953 if (vmap->buf) {
954 MEM_freeN(vmap->buf);
955 }
956 MEM_freeN(vmap);
957 }
958 }
959
BM_uv_element_map_free(UvElementMap * element_map)960 void BM_uv_element_map_free(UvElementMap *element_map)
961 {
962 if (element_map) {
963 if (element_map->vert) {
964 MEM_freeN(element_map->vert);
965 }
966 if (element_map->buf) {
967 MEM_freeN(element_map->buf);
968 }
969 if (element_map->islandIndices) {
970 MEM_freeN(element_map->islandIndices);
971 }
972 MEM_freeN(element_map);
973 }
974 }
975
BM_uv_element_get(UvElementMap * map,BMFace * efa,BMLoop * l)976 UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
977 {
978 for (UvElement *element = map->vert[BM_elem_index_get(l->v)]; element; element = element->next) {
979 if (element->l->f == efa) {
980 return element;
981 }
982 }
983
984 return NULL;
985 }
986
987 /** \} */
988
989 /* -------------------------------------------------------------------- */
990 /** \name Data Layer Checks
991 * \{ */
992
993 /**
994 * last_sel, use em->act_face otherwise get the last selected face in the editselections
995 * at the moment, last_sel is mainly useful for making sure the space image doesn't flicker.
996 */
EDBM_uv_active_face_get(BMEditMesh * em,const bool sloppy,const bool selected)997 BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool selected)
998 {
999 BMFace *efa = NULL;
1000
1001 if (!EDBM_uv_check(em)) {
1002 return NULL;
1003 }
1004
1005 efa = BM_mesh_active_face_get(em->bm, sloppy, selected);
1006
1007 if (efa) {
1008 return efa;
1009 }
1010
1011 return NULL;
1012 }
1013
1014 /* can we edit UV's for this mesh?*/
EDBM_uv_check(BMEditMesh * em)1015 bool EDBM_uv_check(BMEditMesh *em)
1016 {
1017 /* some of these checks could be a touch overkill */
1018 return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV);
1019 }
1020
EDBM_vert_color_check(BMEditMesh * em)1021 bool EDBM_vert_color_check(BMEditMesh *em)
1022 {
1023 /* some of these checks could be a touch overkill */
1024 return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
1025 }
1026
1027 /** \} */
1028
1029 /* -------------------------------------------------------------------- */
1030 /** \name Mirror Cache API
1031 * \{ */
1032
cache_mirr_intptr_as_bmvert(const intptr_t * index_lookup,int index)1033 static BMVert *cache_mirr_intptr_as_bmvert(const intptr_t *index_lookup, int index)
1034 {
1035 intptr_t eve_i = index_lookup[index];
1036 return (eve_i == -1) ? NULL : (BMVert *)eve_i;
1037 }
1038
1039 /**
1040 * Mirror editing API, usage:
1041 *
1042 * \code{.c}
1043 * EDBM_verts_mirror_cache_begin(em, ...);
1044 *
1045 * BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
1046 * v_mirror = EDBM_verts_mirror_get(em, v);
1047 * e_mirror = EDBM_verts_mirror_get_edge(em, e);
1048 * f_mirror = EDBM_verts_mirror_get_face(em, f);
1049 * }
1050 *
1051 * EDBM_verts_mirror_cache_end(em);
1052 * \endcode
1053 */
1054
1055 /* BM_SEARCH_MAXDIST is too big, copied from 2.6x MOC_THRESH, should become a
1056 * preference */
1057 #define BM_SEARCH_MAXDIST_MIRR 0.00002f
1058 #define BM_CD_LAYER_ID "__mirror_index"
1059 /**
1060 * \param em: Editmesh.
1061 * \param use_self: Allow a vertex to point to its self (middle verts).
1062 * \param use_select: Restrict to selected verts.
1063 * \param respecthide: Skip hidden vertices.
1064 * \param use_topology: Use topology mirror.
1065 * \param maxdist: Distance for close point test.
1066 * \param r_index: Optional array to write into, as an alternative to a customdata layer
1067 * (length of total verts).
1068 */
EDBM_verts_mirror_cache_begin_ex(BMEditMesh * em,const int axis,const bool use_self,const bool use_select,const bool respecthide,const bool use_topology,float maxdist,int * r_index)1069 void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
1070 const int axis,
1071 const bool use_self,
1072 const bool use_select,
1073 const bool respecthide,
1074 /* extra args */
1075 const bool use_topology,
1076 float maxdist,
1077 int *r_index)
1078 {
1079 BMesh *bm = em->bm;
1080 BMIter iter;
1081 BMVert *v;
1082 int cd_vmirr_offset = 0;
1083 int i;
1084 const float maxdist_sq = square_f(maxdist);
1085
1086 /* one or the other is used depending if topo is enabled */
1087 KDTree_3d *tree = NULL;
1088 MirrTopoStore_t mesh_topo_store = {NULL, -1, -1, -1};
1089
1090 BM_mesh_elem_table_ensure(bm, BM_VERT);
1091
1092 if (r_index == NULL) {
1093 const char *layer_id = BM_CD_LAYER_ID;
1094 em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT32, layer_id);
1095 if (em->mirror_cdlayer == -1) {
1096 BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT32, layer_id);
1097 em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT32, layer_id);
1098 }
1099
1100 cd_vmirr_offset = CustomData_get_n_offset(
1101 &bm->vdata,
1102 CD_PROP_INT32,
1103 em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT32));
1104
1105 bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY;
1106 }
1107
1108 BM_mesh_elem_index_ensure(bm, BM_VERT);
1109
1110 if (use_topology) {
1111 ED_mesh_mirrtopo_init(em, NULL, &mesh_topo_store, true);
1112 }
1113 else {
1114 tree = BLI_kdtree_3d_new(bm->totvert);
1115 BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
1116 if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
1117 continue;
1118 }
1119
1120 BLI_kdtree_3d_insert(tree, i, v->co);
1121 }
1122 BLI_kdtree_3d_balance(tree);
1123 }
1124
1125 #define VERT_INTPTR(_v, _i) (r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset))
1126
1127 BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
1128 if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
1129 continue;
1130 }
1131
1132 if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) {
1133 continue;
1134 }
1135
1136 BLI_assert(BM_elem_index_get(v) == i);
1137 BMVert *v_mirr;
1138 int *idx = VERT_INTPTR(v, i);
1139
1140 if (use_topology) {
1141 v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
1142 }
1143 else {
1144 int i_mirr;
1145 float co[3];
1146 copy_v3_v3(co, v->co);
1147 co[axis] *= -1.0f;
1148
1149 v_mirr = NULL;
1150 i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL);
1151 if (i_mirr != -1) {
1152 BMVert *v_test = BM_vert_at_index(bm, i_mirr);
1153 if (len_squared_v3v3(co, v_test->co) < maxdist_sq) {
1154 v_mirr = v_test;
1155 }
1156 }
1157 }
1158
1159 if (v_mirr && (use_self || (v_mirr != v))) {
1160 const int i_mirr = BM_elem_index_get(v_mirr);
1161 *idx = i_mirr;
1162 idx = VERT_INTPTR(v_mirr, i_mirr);
1163 *idx = i;
1164 }
1165 else {
1166 *idx = -1;
1167 }
1168 }
1169
1170 #undef VERT_INTPTR
1171
1172 if (use_topology) {
1173 ED_mesh_mirrtopo_free(&mesh_topo_store);
1174 }
1175 else {
1176 BLI_kdtree_3d_free(tree);
1177 }
1178 }
1179
EDBM_verts_mirror_cache_begin(BMEditMesh * em,const int axis,const bool use_self,const bool use_select,const bool respecthide,const bool use_topology)1180 void EDBM_verts_mirror_cache_begin(BMEditMesh *em,
1181 const int axis,
1182 const bool use_self,
1183 const bool use_select,
1184 const bool respecthide,
1185 const bool use_topology)
1186 {
1187 EDBM_verts_mirror_cache_begin_ex(em,
1188 axis,
1189 use_self,
1190 use_select,
1191 respecthide,
1192 /* extra args */
1193 use_topology,
1194 BM_SEARCH_MAXDIST_MIRR,
1195 NULL);
1196 }
1197
EDBM_verts_mirror_get(BMEditMesh * em,BMVert * v)1198 BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v)
1199 {
1200 const int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
1201
1202 BLI_assert(em->mirror_cdlayer != -1); /* invalid use */
1203
1204 if (mirr && *mirr >= 0 && *mirr < em->bm->totvert) {
1205 if (!em->bm->vtable) {
1206 printf(
1207 "err: should only be called between "
1208 "EDBM_verts_mirror_cache_begin and EDBM_verts_mirror_cache_end");
1209 return NULL;
1210 }
1211
1212 return em->bm->vtable[*mirr];
1213 }
1214
1215 return NULL;
1216 }
1217
EDBM_verts_mirror_get_edge(BMEditMesh * em,BMEdge * e)1218 BMEdge *EDBM_verts_mirror_get_edge(BMEditMesh *em, BMEdge *e)
1219 {
1220 BMVert *v1_mirr = EDBM_verts_mirror_get(em, e->v1);
1221 if (v1_mirr) {
1222 BMVert *v2_mirr = EDBM_verts_mirror_get(em, e->v2);
1223 if (v2_mirr) {
1224 return BM_edge_exists(v1_mirr, v2_mirr);
1225 }
1226 }
1227
1228 return NULL;
1229 }
1230
EDBM_verts_mirror_get_face(BMEditMesh * em,BMFace * f)1231 BMFace *EDBM_verts_mirror_get_face(BMEditMesh *em, BMFace *f)
1232 {
1233 BMVert **v_mirr_arr = BLI_array_alloca(v_mirr_arr, f->len);
1234
1235 BMLoop *l_iter, *l_first;
1236 uint i = 0;
1237
1238 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1239 do {
1240 if ((v_mirr_arr[i++] = EDBM_verts_mirror_get(em, l_iter->v)) == NULL) {
1241 return NULL;
1242 }
1243 } while ((l_iter = l_iter->next) != l_first);
1244
1245 return BM_face_exists(v_mirr_arr, f->len);
1246 }
1247
EDBM_verts_mirror_cache_clear(BMEditMesh * em,BMVert * v)1248 void EDBM_verts_mirror_cache_clear(BMEditMesh *em, BMVert *v)
1249 {
1250 int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
1251
1252 BLI_assert(em->mirror_cdlayer != -1); /* invalid use */
1253
1254 if (mirr) {
1255 *mirr = -1;
1256 }
1257 }
1258
EDBM_verts_mirror_cache_end(BMEditMesh * em)1259 void EDBM_verts_mirror_cache_end(BMEditMesh *em)
1260 {
1261 em->mirror_cdlayer = -1;
1262 }
1263
EDBM_verts_mirror_apply(BMEditMesh * em,const int sel_from,const int sel_to)1264 void EDBM_verts_mirror_apply(BMEditMesh *em, const int sel_from, const int sel_to)
1265 {
1266 BMIter iter;
1267 BMVert *v;
1268
1269 BLI_assert((em->bm->vtable != NULL) && ((em->bm->elem_table_dirty & BM_VERT) == 0));
1270
1271 BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
1272 if (BM_elem_flag_test(v, BM_ELEM_SELECT) == sel_from) {
1273 BMVert *mirr = EDBM_verts_mirror_get(em, v);
1274 if (mirr) {
1275 if (BM_elem_flag_test(mirr, BM_ELEM_SELECT) == sel_to) {
1276 copy_v3_v3(mirr->co, v->co);
1277 mirr->co[0] *= -1.0f;
1278 }
1279 }
1280 }
1281 }
1282 }
1283
1284 /** \} */
1285
1286 /* -------------------------------------------------------------------- */
1287 /** \name Hide/Reveal API
1288 * \{ */
1289
1290 /* swap is 0 or 1, if 1 it hides not selected */
EDBM_mesh_hide(BMEditMesh * em,bool swap)1291 bool EDBM_mesh_hide(BMEditMesh *em, bool swap)
1292 {
1293 BMIter iter;
1294 BMElem *ele;
1295 int itermode;
1296 char hflag_swap = swap ? BM_ELEM_SELECT : 0;
1297 bool changed = true;
1298
1299 if (em->selectmode & SCE_SELECT_VERTEX) {
1300 itermode = BM_VERTS_OF_MESH;
1301 }
1302 else if (em->selectmode & SCE_SELECT_EDGE) {
1303 itermode = BM_EDGES_OF_MESH;
1304 }
1305 else {
1306 itermode = BM_FACES_OF_MESH;
1307 }
1308
1309 BM_ITER_MESH (ele, &iter, em->bm, itermode) {
1310 if (!BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
1311 if (BM_elem_flag_test(ele, BM_ELEM_SELECT) ^ hflag_swap) {
1312 BM_elem_hide_set(em->bm, ele, true);
1313 changed = true;
1314 }
1315 }
1316 }
1317
1318 if (changed) {
1319 EDBM_selectmode_flush(em);
1320 }
1321 return changed;
1322
1323 /* original hide flushing comment (OUTDATED):
1324 * hide happens on least dominant select mode, and flushes up, not down!
1325 * (helps preventing errors in subsurf) */
1326 /* - vertex hidden, always means edge is hidden too
1327 * - edge hidden, always means face is hidden too
1328 * - face hidden, only set face hide
1329 * - then only flush back down what's absolute hidden
1330 */
1331 }
1332
EDBM_mesh_reveal(BMEditMesh * em,bool select)1333 bool EDBM_mesh_reveal(BMEditMesh *em, bool select)
1334 {
1335 const char iter_types[3] = {
1336 BM_VERTS_OF_MESH,
1337 BM_EDGES_OF_MESH,
1338 BM_FACES_OF_MESH,
1339 };
1340
1341 const bool sels[3] = {
1342 (em->selectmode & SCE_SELECT_VERTEX) != 0,
1343 (em->selectmode & SCE_SELECT_EDGE) != 0,
1344 (em->selectmode & SCE_SELECT_FACE) != 0,
1345 };
1346 int i;
1347 bool changed = false;
1348
1349 /* Use tag flag to remember what was hidden before all is revealed.
1350 * BM_ELEM_HIDDEN --> BM_ELEM_TAG */
1351 for (i = 0; i < 3; i++) {
1352 BMIter iter;
1353 BMElem *ele;
1354
1355 BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
1356 if (BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
1357 BM_elem_flag_enable(ele, BM_ELEM_TAG);
1358 changed = true;
1359 }
1360 else {
1361 BM_elem_flag_disable(ele, BM_ELEM_TAG);
1362 }
1363 }
1364 }
1365
1366 if (!changed) {
1367 return false;
1368 }
1369
1370 /* Reveal everything */
1371 EDBM_flag_disable_all(em, BM_ELEM_HIDDEN);
1372
1373 /* Select relevant just-revealed elements */
1374 for (i = 0; i < 3; i++) {
1375 BMIter iter;
1376 BMElem *ele;
1377
1378 if (!sels[i]) {
1379 continue;
1380 }
1381
1382 BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
1383 if (BM_elem_flag_test(ele, BM_ELEM_TAG)) {
1384 BM_elem_select_set(em->bm, ele, select);
1385 }
1386 }
1387 }
1388
1389 EDBM_selectmode_flush(em);
1390
1391 /* hidden faces can have invalid normals */
1392 EDBM_mesh_normals_update(em);
1393
1394 return true;
1395 }
1396
1397 /** \} */
1398
1399 /* -------------------------------------------------------------------- */
1400 /** \name Update API
1401 * \{ */
1402
EDBM_mesh_normals_update(BMEditMesh * em)1403 void EDBM_mesh_normals_update(BMEditMesh *em)
1404 {
1405 BM_mesh_normals_update(em->bm);
1406 }
1407
EDBM_stats_update(BMEditMesh * em)1408 void EDBM_stats_update(BMEditMesh *em)
1409 {
1410 const char iter_types[3] = {
1411 BM_VERTS_OF_MESH,
1412 BM_EDGES_OF_MESH,
1413 BM_FACES_OF_MESH,
1414 };
1415
1416 BMIter iter;
1417 BMElem *ele;
1418 int *tots[3];
1419 int i;
1420
1421 tots[0] = &em->bm->totvertsel;
1422 tots[1] = &em->bm->totedgesel;
1423 tots[2] = &em->bm->totfacesel;
1424
1425 em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
1426
1427 for (i = 0; i < 3; i++) {
1428 ele = BM_iter_new(&iter, em->bm, iter_types[i], NULL);
1429 for (; ele; ele = BM_iter_step(&iter)) {
1430 if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
1431 (*tots[i])++;
1432 }
1433 }
1434 }
1435 }
1436
1437 /* so many tools call these that we better make it a generic function.
1438 */
EDBM_update_generic(Mesh * mesh,const bool do_tessellation,const bool is_destructive)1439 void EDBM_update_generic(Mesh *mesh, const bool do_tessellation, const bool is_destructive)
1440 {
1441 BMEditMesh *em = mesh->edit_mesh;
1442 /* Order of calling isn't important. */
1443 DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
1444 WM_main_add_notifier(NC_GEOM | ND_DATA, &mesh->id);
1445
1446 if (do_tessellation) {
1447 BKE_editmesh_looptri_calc(em);
1448 }
1449
1450 if (is_destructive) {
1451 /* TODO. we may be able to remove this now! - Campbell */
1452 // BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP);
1453 }
1454 else {
1455 /* in debug mode double check we didn't need to recalculate */
1456 BLI_assert(BM_mesh_elem_table_check(em->bm) == true);
1457 }
1458 if (em->bm->spacearr_dirty & BM_SPACEARR_BMO_SET) {
1459 BM_lnorspace_invalidate(em->bm, false);
1460 em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET;
1461 }
1462 /* don't keep stale derivedMesh data around, see: T38872. */
1463 BKE_editmesh_free_derivedmesh(em);
1464
1465 #ifdef DEBUG
1466 {
1467 BMEditSelection *ese;
1468 for (ese = em->bm->selected.first; ese; ese = ese->next) {
1469 BLI_assert(BM_elem_flag_test(ese->ele, BM_ELEM_SELECT));
1470 }
1471 }
1472 #endif
1473 }
1474
1475 /** \} */
1476
1477 /* -------------------------------------------------------------------- */
1478 /** \name Operator Helpers
1479 * \{ */
1480
1481 /* poll call for mesh operators requiring a view3d context */
EDBM_view3d_poll(bContext * C)1482 bool EDBM_view3d_poll(bContext *C)
1483 {
1484 if (ED_operator_editmesh(C) && ED_operator_view3d_active(C)) {
1485 return 1;
1486 }
1487
1488 return 0;
1489 }
1490
1491 /** \} */
1492
1493 /* -------------------------------------------------------------------- */
1494 /** \name BMesh Element API
1495 * \{ */
1496
EDBM_elem_from_selectmode(BMEditMesh * em,BMVert * eve,BMEdge * eed,BMFace * efa)1497 BMElem *EDBM_elem_from_selectmode(BMEditMesh *em, BMVert *eve, BMEdge *eed, BMFace *efa)
1498 {
1499 BMElem *ele = NULL;
1500
1501 if ((em->selectmode & SCE_SELECT_VERTEX) && eve) {
1502 ele = (BMElem *)eve;
1503 }
1504 else if ((em->selectmode & SCE_SELECT_EDGE) && eed) {
1505 ele = (BMElem *)eed;
1506 }
1507 else if ((em->selectmode & SCE_SELECT_FACE) && efa) {
1508 ele = (BMElem *)efa;
1509 }
1510
1511 return ele;
1512 }
1513
1514 /**
1515 * Used when we want to store a single index for any vert/edge/face.
1516 *
1517 * Intended for use with operators.
1518 */
EDBM_elem_to_index_any(BMEditMesh * em,BMElem * ele)1519 int EDBM_elem_to_index_any(BMEditMesh *em, BMElem *ele)
1520 {
1521 BMesh *bm = em->bm;
1522 int index = BM_elem_index_get(ele);
1523
1524 if (ele->head.htype == BM_VERT) {
1525 BLI_assert(!(bm->elem_index_dirty & BM_VERT));
1526 }
1527 else if (ele->head.htype == BM_EDGE) {
1528 BLI_assert(!(bm->elem_index_dirty & BM_EDGE));
1529 index += bm->totvert;
1530 }
1531 else if (ele->head.htype == BM_FACE) {
1532 BLI_assert(!(bm->elem_index_dirty & BM_FACE));
1533 index += bm->totvert + bm->totedge;
1534 }
1535 else {
1536 BLI_assert(0);
1537 }
1538
1539 return index;
1540 }
1541
EDBM_elem_from_index_any(BMEditMesh * em,int index)1542 BMElem *EDBM_elem_from_index_any(BMEditMesh *em, int index)
1543 {
1544 BMesh *bm = em->bm;
1545
1546 if (index < bm->totvert) {
1547 return (BMElem *)BM_vert_at_index_find_or_table(bm, index);
1548 }
1549 index -= bm->totvert;
1550 if (index < bm->totedge) {
1551 return (BMElem *)BM_edge_at_index_find_or_table(bm, index);
1552 }
1553 index -= bm->totedge;
1554 if (index < bm->totface) {
1555 return (BMElem *)BM_face_at_index_find_or_table(bm, index);
1556 }
1557
1558 return NULL;
1559 }
1560
EDBM_elem_to_index_any_multi(ViewLayer * view_layer,BMEditMesh * em,BMElem * ele,int * r_object_index)1561 int EDBM_elem_to_index_any_multi(ViewLayer *view_layer,
1562 BMEditMesh *em,
1563 BMElem *ele,
1564 int *r_object_index)
1565 {
1566 uint bases_len;
1567 int elem_index = -1;
1568 *r_object_index = -1;
1569 Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len);
1570 for (uint base_index = 0; base_index < bases_len; base_index++) {
1571 Base *base_iter = bases[base_index];
1572 if (BKE_editmesh_from_object(base_iter->object) == em) {
1573 *r_object_index = base_index;
1574 elem_index = EDBM_elem_to_index_any(em, ele);
1575 break;
1576 }
1577 }
1578 MEM_freeN(bases);
1579 return elem_index;
1580 }
1581
EDBM_elem_from_index_any_multi(ViewLayer * view_layer,int object_index,int elem_index,Object ** r_obedit)1582 BMElem *EDBM_elem_from_index_any_multi(ViewLayer *view_layer,
1583 int object_index,
1584 int elem_index,
1585 Object **r_obedit)
1586 {
1587 uint bases_len;
1588 Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len);
1589 *r_obedit = NULL;
1590 Object *obedit = ((uint)object_index < bases_len) ? bases[object_index]->object : NULL;
1591 MEM_freeN(bases);
1592 if (obedit != NULL) {
1593 BMEditMesh *em = BKE_editmesh_from_object(obedit);
1594 BMElem *ele = EDBM_elem_from_index_any(em, elem_index);
1595 if (ele != NULL) {
1596 *r_obedit = obedit;
1597 return ele;
1598 }
1599 }
1600 return NULL;
1601 }
1602
1603 /** \} */
1604
1605 /* -------------------------------------------------------------------- */
1606 /** \name BMesh BVH API
1607 * \{ */
1608
edge_ray_cast(struct BMBVHTree * tree,const float co[3],const float dir[3],float * r_hitout,BMEdge * e)1609 static BMFace *edge_ray_cast(
1610 struct BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e)
1611 {
1612 BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL);
1613
1614 if (f && BM_edge_in_face(e, f)) {
1615 return NULL;
1616 }
1617
1618 return f;
1619 }
1620
scale_point(float c1[3],const float p[3],const float s)1621 static void scale_point(float c1[3], const float p[3], const float s)
1622 {
1623 sub_v3_v3(c1, p);
1624 mul_v3_fl(c1, s);
1625 add_v3_v3(c1, p);
1626 }
1627
BMBVH_EdgeVisible(struct BMBVHTree * tree,BMEdge * e,struct Depsgraph * depsgraph,ARegion * region,View3D * v3d,Object * obedit)1628 bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
1629 BMEdge *e,
1630 struct Depsgraph *depsgraph,
1631 ARegion *region,
1632 View3D *v3d,
1633 Object *obedit)
1634 {
1635 BMFace *f;
1636 float co1[3], co2[3], co3[3], dir1[3], dir2[3], dir3[3];
1637 float origin[3], invmat[4][4];
1638 float epsilon = 0.01f;
1639 float end[3];
1640 const float mval_f[2] = {
1641 region->winx / 2.0f,
1642 region->winy / 2.0f,
1643 };
1644
1645 ED_view3d_win_to_segment_clipped(depsgraph, region, v3d, mval_f, origin, end, false);
1646
1647 invert_m4_m4(invmat, obedit->obmat);
1648 mul_m4_v3(invmat, origin);
1649
1650 copy_v3_v3(co1, e->v1->co);
1651 mid_v3_v3v3(co2, e->v1->co, e->v2->co);
1652 copy_v3_v3(co3, e->v2->co);
1653
1654 scale_point(co1, co2, 0.99);
1655 scale_point(co3, co2, 0.99);
1656
1657 /* ok, idea is to generate rays going from the camera origin to the
1658 * three points on the edge (v1, mid, v2)*/
1659 sub_v3_v3v3(dir1, origin, co1);
1660 sub_v3_v3v3(dir2, origin, co2);
1661 sub_v3_v3v3(dir3, origin, co3);
1662
1663 normalize_v3_length(dir1, epsilon);
1664 normalize_v3_length(dir2, epsilon);
1665 normalize_v3_length(dir3, epsilon);
1666
1667 /* offset coordinates slightly along view vectors, to avoid
1668 * hitting the faces that own the edge.*/
1669 add_v3_v3v3(co1, co1, dir1);
1670 add_v3_v3v3(co2, co2, dir2);
1671 add_v3_v3v3(co3, co3, dir3);
1672
1673 normalize_v3(dir1);
1674 normalize_v3(dir2);
1675 normalize_v3(dir3);
1676
1677 /* do three samplings: left, middle, right */
1678 f = edge_ray_cast(tree, co1, dir1, NULL, e);
1679 if (f && !edge_ray_cast(tree, co2, dir2, NULL, e)) {
1680 return true;
1681 }
1682 if (f && !edge_ray_cast(tree, co3, dir3, NULL, e)) {
1683 return true;
1684 }
1685 if (!f) {
1686 return true;
1687 }
1688
1689 return false;
1690 }
1691
1692 /** \} */
1693
1694 /* -------------------------------------------------------------------- */
1695 /** \name BMesh Vertex Projection API
1696 * \{ */
1697
EDBM_project_snap_verts(bContext * C,Depsgraph * depsgraph,ARegion * region,Object * obedit,BMEditMesh * em)1698 void EDBM_project_snap_verts(
1699 bContext *C, Depsgraph *depsgraph, ARegion *region, Object *obedit, BMEditMesh *em)
1700 {
1701 BMIter iter;
1702 BMVert *eve;
1703
1704 ED_view3d_init_mats_rv3d(obedit, region->regiondata);
1705
1706 struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
1707 CTX_data_scene(C), 0, region, CTX_wm_view3d(C));
1708
1709 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1710 if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
1711 float mval[2], co_proj[3];
1712 if (ED_view3d_project_float_object(region, eve->co, mval, V3D_PROJ_TEST_NOP) ==
1713 V3D_PROJ_RET_OK) {
1714 if (ED_transform_snap_object_project_view3d(snap_context,
1715 depsgraph,
1716 SCE_SNAP_MODE_FACE,
1717 &(const struct SnapObjectParams){
1718 .snap_select = SNAP_NOT_ACTIVE,
1719 .use_object_edit_cage = false,
1720 .use_occlusion_test = true,
1721 },
1722 mval,
1723 NULL,
1724 NULL,
1725 co_proj,
1726 NULL)) {
1727 mul_v3_m4v3(eve->co, obedit->imat, co_proj);
1728 }
1729 }
1730 }
1731 }
1732
1733 ED_transform_snap_object_context_destroy(snap_context);
1734 }
1735
1736 /** \} */
1737