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