Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / mesh / editmesh_rip.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * 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_object_types.h"
27
28 #include "BLI_math.h"
29 #include "BLI_array.h"
30
31 #include "BKE_context.h"
32 #include "BKE_report.h"
33 #include "BKE_editmesh.h"
34 #include "BKE_layer.h"
35
36 #include "RNA_define.h"
37 #include "RNA_access.h"
38
39 #include "WM_types.h"
40
41 #include "ED_mesh.h"
42 #include "ED_screen.h"
43 #include "ED_transform.h"
44 #include "ED_view3d.h"
45
46 #include "bmesh.h"
47 #include "bmesh_tools.h"
48
49 #include "mesh_intern.h" /* own include */
50
51 /**
52  * helper to find edge for edge_rip,
53  *
54  * \param inset: is used so we get some useful distance
55  * when comparing multiple edges that meet at the same
56  * point and would result in the same distance.
57  */
58 #define INSET_DEFAULT 0.00001f
59 static float edbm_rip_edgedist_squared(ARegion *ar,
60                                        float mat[4][4],
61                                        const float co1[3],
62                                        const float co2[3],
63                                        const float mvalf[2],
64                                        const float inset)
65 {
66   float vec1[2], vec2[2], dist_sq;
67
68   ED_view3d_project_float_v2_m4(ar, co1, vec1, mat);
69   ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
70
71   if (inset != 0.0f) {
72     const float dist_2d = len_v2v2(vec1, vec2);
73     if (dist_2d > FLT_EPSILON) {
74       const float dist = inset / dist_2d;
75       BLI_assert(isfinite(dist));
76       interp_v2_v2v2(vec1, vec1, vec2, dist);
77       interp_v2_v2v2(vec2, vec2, vec1, dist);
78     }
79   }
80
81   dist_sq = dist_squared_to_line_segment_v2(mvalf, vec1, vec2);
82   BLI_assert(isfinite(dist_sq));
83
84   return dist_sq;
85 }
86
87 #if 0
88 static float edbm_rip_linedist(
89     ARegion *ar, float mat[4][4], const float co1[3], const float co2[3], const float mvalf[2])
90 {
91   float vec1[2], vec2[2];
92
93   ED_view3d_project_float_v2_m4(ar, co1, vec1, mat);
94   ED_view3d_project_float_v2_m4(ar, co2, vec2, mat);
95
96   return dist_to_line_v2(mvalf, vec1, vec2);
97 }
98 #endif
99
100 /* calculaters a point along the loop tangent which can be used to measure against edges */
101 static void edbm_calc_loop_co(BMLoop *l, float l_mid_co[3])
102 {
103   BM_loop_calc_face_tangent(l, l_mid_co);
104
105   /* scale to average of surrounding edge size, only needs to be approx, but should
106    * be roughly equivalent to the check below which uses the middle of the edge. */
107   mul_v3_fl(l_mid_co, (BM_edge_calc_length(l->e) + BM_edge_calc_length(l->prev->e)) / 2.0f);
108
109   add_v3_v3(l_mid_co, l->v->co);
110 }
111
112 static float edbm_rip_edge_side_measure(
113     BMEdge *e, BMLoop *e_l, ARegion *ar, float projectMat[4][4], const float fmval[2])
114 {
115   float cent[3] = {0, 0, 0}, mid[3];
116
117   float vec[2];
118   float fmval_tweak[2];
119   float e_v1_co[2], e_v2_co[2];
120   float score;
121
122   BMVert *v1_other;
123   BMVert *v2_other;
124
125   BLI_assert(BM_vert_in_edge(e, e_l->v));
126
127   /* method for calculating distance:
128    *
129    * for each edge: calculate face center, then made a vector
130    * from edge midpoint to face center.  offset edge midpoint
131    * by a small amount along this vector. */
132
133   /* rather then the face center, get the middle of
134    * both edge verts connected to this one */
135   v1_other = BM_face_other_vert_loop(e_l->f, e->v2, e->v1)->v;
136   v2_other = BM_face_other_vert_loop(e_l->f, e->v1, e->v2)->v;
137   mid_v3_v3v3(cent, v1_other->co, v2_other->co);
138   mid_v3_v3v3(mid, e->v1->co, e->v2->co);
139
140   ED_view3d_project_float_v2_m4(ar, cent, cent, projectMat);
141   ED_view3d_project_float_v2_m4(ar, mid, mid, projectMat);
142
143   ED_view3d_project_float_v2_m4(ar, e->v1->co, e_v1_co, projectMat);
144   ED_view3d_project_float_v2_m4(ar, e->v2->co, e_v2_co, projectMat);
145
146   sub_v2_v2v2(vec, cent, mid);
147   normalize_v2_length(vec, 0.01f);
148
149   /* rather then adding to both verts, subtract from the mouse */
150   sub_v2_v2v2(fmval_tweak, fmval, vec);
151
152   score = len_v2v2(e_v1_co, e_v2_co);
153
154   if (dist_squared_to_line_segment_v2(fmval_tweak, e_v1_co, e_v2_co) >
155       dist_squared_to_line_segment_v2(fmval, e_v1_co, e_v2_co)) {
156     return score;
157   }
158   else {
159     return -score;
160   }
161 }
162
163 /* - Advanced selection handling 'ripsel' functions ----- */
164
165 /**
166  * How rip selection works
167  *
168  * Firstly - rip is basically edge split with side-selection & grab.
169  * Things would be much more simple if we didn't have to worry about side selection
170  *
171  * The method used for checking the side of selection is as follows...
172  * - First tag all rip-able edges.
173  * - Build a contiguous edge list by looping over tagged edges and following each ones tagged
174  *   siblings in both directions.
175  *   - The loops are not stored in an array, Instead both loops on either side of each edge has
176  *     its index values set to count down from the last edge, this way, once we have the 'last'
177  *     edge its very easy to walk down the connected edge loops.
178  *     The reason for using loops like this is because when the edges are split we don't which
179  *     face user gets the newly created edge
180  *     (its as good as random so we cant assume new edges will be on once side).
181  *     After splitting, its very simple to walk along boundary loops since each only has one edge
182  *     from a single side.
183  * - The end loop pairs are stored in an array however to support multiple edge-selection-islands,
184  *   so you can rip multiple selections at once.
185  * - * Execute the split *
186  * - For each #EdgeLoopPair walk down both sides of the split using the loops and measure
187  *   which is facing the mouse.
188  * - Deselect the edge loop facing away.
189  *
190  * Limitation!
191  * This currently works very poorly with intersecting edge islands
192  * (verts with more than 2 tagged edges). This is nice to but for now not essential.
193  *
194  * - campbell.
195  */
196
197 #define IS_VISIT_POSSIBLE(e) (BM_edge_is_manifold(e) && BM_elem_flag_test(e, BM_ELEM_TAG))
198 #define IS_VISIT_DONE(e) ((e)->l && (BM_elem_index_get((e)->l) != INVALID_UID))
199 #define INVALID_UID INT_MIN
200
201 /* mark, assign uid and step */
202 static BMEdge *edbm_ripsel_edge_mark_step(BMVert *v, const int uid)
203 {
204   BMIter iter;
205   BMEdge *e;
206   BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
207     if (IS_VISIT_POSSIBLE(e) && !IS_VISIT_DONE(e)) {
208       BMLoop *l_a, *l_b;
209
210       BM_edge_loop_pair(e, &l_a, &l_b); /* no need to check, we know this will be true */
211
212       /* so (IS_VISIT_DONE == true) */
213       BM_elem_index_set(l_a, uid); /* set_dirty */
214       BM_elem_index_set(l_b, uid); /* set_dirty */
215
216       return e;
217     }
218   }
219   return NULL;
220 }
221
222 typedef struct EdgeLoopPair {
223   BMLoop *l_a;
224   BMLoop *l_b;
225 } EdgeLoopPair;
226
227 static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm)
228 {
229   BMIter fiter;
230   BMIter liter;
231
232   BMFace *f;
233   BMLoop *l;
234
235   int uid_start;
236   int uid_end;
237   int uid = bm->totedge; /* can start anywhere */
238
239   EdgeLoopPair *eloop_pairs = NULL;
240   BLI_array_declare(eloop_pairs);
241   EdgeLoopPair *lp;
242
243   /* initialize loops with dummy invalid index values */
244   BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
245     BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
246       BM_elem_index_set(l, INVALID_UID); /* set_dirty */
247     }
248   }
249   bm->elem_index_dirty |= BM_LOOP;
250
251   /* set contiguous loops ordered 'uid' values for walking after split */
252   while (true) {
253     int tot = 0;
254     BMIter eiter;
255     BMEdge *e_step;
256     BMVert *v_step;
257     BMEdge *e;
258     BMEdge *e_first;
259     BMEdge *e_last;
260
261     e_first = NULL;
262     BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
263       if (IS_VISIT_POSSIBLE(e) && !IS_VISIT_DONE(e)) {
264         e_first = e;
265         break;
266       }
267     }
268
269     if (e_first == NULL) {
270       break;
271     }
272
273     /* initialize  */
274     e_first = e;
275     v_step = e_first->v1;
276     e_step = NULL; /* quiet warning, will never remain this value */
277
278     uid_start = uid;
279     while ((e = edbm_ripsel_edge_mark_step(v_step, uid))) {
280       v_step = BM_edge_other_vert((e_step = e), v_step);
281       uid++; /* only different line */
282       tot++;
283     }
284
285     /* this edges loops have the highest uid's, store this to walk down later */
286     e_last = e_step;
287
288     /* always store the highest 'uid' edge for the stride */
289     uid_end = uid - 1;
290     uid = uid_start - 1;
291
292     /* initialize */
293     v_step = e_first->v1;
294
295     while ((e = edbm_ripsel_edge_mark_step(v_step, uid))) {
296       v_step = BM_edge_other_vert((e_step = e), v_step);
297       uid--; /* only different line */
298       tot++;
299     }
300
301     /* stride far enough not to _ever_ overlap range */
302     uid_start = uid;
303     uid = uid_end + bm->totedge;
304
305     lp = BLI_array_append_ret(eloop_pairs);
306     /* no need to check, we know this will be true */
307     BM_edge_loop_pair(e_last, &lp->l_a, &lp->l_b);
308
309     BLI_assert(tot == uid_end - uid_start);
310
311 #if 0
312     printf("%s: found contiguous edge loop of (%d)\n", __func__, uid_end - uid_start);
313 #endif
314   }
315
316   /* null terminate */
317   lp = BLI_array_append_ret(eloop_pairs);
318   lp->l_a = lp->l_b = NULL;
319
320   return eloop_pairs;
321 }
322
323 /* - De-Select the worst rip-edge side -------------------------------- */
324
325 static BMEdge *edbm_ripsel_edge_uid_step(BMEdge *e_orig, BMVert **v_prev)
326 {
327   BMIter eiter;
328   BMEdge *e;
329   BMVert *v = BM_edge_other_vert(e_orig, *v_prev);
330   const int uid_cmp = BM_elem_index_get(e_orig->l) - 1;
331
332   BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
333     if (BM_elem_index_get(e->l) == uid_cmp) {
334       *v_prev = v;
335       return e;
336     }
337   }
338   return NULL;
339 }
340
341 static BMVert *edbm_ripsel_edloop_pair_start_vert(BMEdge *e)
342 {
343   /* try step in a direction, if it fails we know do go the other way */
344   BMVert *v_test = e->v1;
345   return (edbm_ripsel_edge_uid_step(e, &v_test)) ? e->v1 : e->v2;
346 }
347
348 static void edbm_ripsel_deselect_helper(
349     BMesh *bm, EdgeLoopPair *eloop_pairs, ARegion *ar, float projectMat[4][4], float fmval[2])
350 {
351   EdgeLoopPair *lp;
352
353   for (lp = eloop_pairs; lp->l_a; lp++) {
354     BMEdge *e;
355     BMVert *v_prev;
356
357     float score_a = 0.0f;
358     float score_b = 0.0f;
359
360     e = lp->l_a->e;
361     v_prev = edbm_ripsel_edloop_pair_start_vert(e);
362     for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) {
363       score_a += edbm_rip_edge_side_measure(e, e->l, ar, projectMat, fmval);
364     }
365     e = lp->l_b->e;
366     v_prev = edbm_ripsel_edloop_pair_start_vert(e);
367     for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) {
368       score_b += edbm_rip_edge_side_measure(e, e->l, ar, projectMat, fmval);
369     }
370
371     e = (score_a > score_b) ? lp->l_a->e : lp->l_b->e;
372     v_prev = edbm_ripsel_edloop_pair_start_vert(e);
373     for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) {
374       BM_edge_select_set(bm, e, false);
375     }
376   }
377 }
378 /* --- end 'ripsel' selection handling code --- */
379
380 /* --- face-fill code --- */
381 /**
382  * return an un-ordered array of loop pairs
383  * use for rebuilding face-fill
384  *
385  * \note the method currently used fails for edges with 3+ face users and gives
386  *       nasty holes in the mesh, there isnt a good way of knowing ahead of time
387  *       which loops will be split apart (its possible to figure out but quite involved).
388  *       So for now this is a known limitation of current rip-fill option.
389  */
390
391 typedef struct UnorderedLoopPair {
392   BMLoop *l_pair[2];
393   char flag;
394 } UnorderedLoopPair;
395 enum {
396   ULP_FLIP_0 = (1 << 0),
397   ULP_FLIP_1 = (1 << 1),
398 };
399
400 static UnorderedLoopPair *edbm_tagged_loop_pairs_to_fill(BMesh *bm)
401 {
402   BMIter iter;
403   BMEdge *e;
404
405   unsigned int total_tag = 0;
406   /* count tags, could be pre-calculated */
407   BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
408     if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
409       total_tag++;
410     }
411   }
412
413   if (total_tag) {
414     UnorderedLoopPair *uloop_pairs = MEM_mallocN(total_tag * sizeof(UnorderedLoopPair), __func__);
415     UnorderedLoopPair *ulp = uloop_pairs;
416
417     BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
418       if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
419         BMLoop *l1, *l2;
420         if (BM_edge_loop_pair(e, &l1, &l2)) {
421           BMVert *v_cmp = l1->e->v1;
422           ulp->flag = (((l1->v != v_cmp) ? ULP_FLIP_0 : 0) | ((l2->v == v_cmp) ? ULP_FLIP_1 : 0));
423         }
424         else {
425           ulp->flag = 0;
426         }
427         ulp->l_pair[0] = l1;
428         ulp->l_pair[1] = l2;
429
430         ulp++;
431       }
432     }
433
434     return uloop_pairs;
435   }
436   else {
437     return NULL;
438   }
439 }
440
441 static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *uloop_pairs)
442 {
443   UnorderedLoopPair *ulp;
444   unsigned int total_tag = MEM_allocN_len(uloop_pairs) / sizeof(UnorderedLoopPair);
445   unsigned int i;
446
447   for (i = 0, ulp = uloop_pairs; i < total_tag; i++, ulp++) {
448     if ((ulp->l_pair[0] && ulp->l_pair[1]) && (ulp->l_pair[0]->e != ulp->l_pair[1]->e)) {
449       /* time has come to make a face! */
450       BMVert *v_shared = BM_edge_share_vert(ulp->l_pair[0]->e, ulp->l_pair[1]->e);
451       BMFace *f, *f_example = ulp->l_pair[0]->f;
452       BMLoop *l_iter;
453       BMVert *f_verts[4];
454
455       if (v_shared == NULL) {
456         /* quad */
457         f_verts[0] = ulp->l_pair[0]->e->v1;
458         f_verts[1] = ulp->l_pair[1]->e->v1;
459         f_verts[2] = ulp->l_pair[1]->e->v2;
460         f_verts[3] = ulp->l_pair[0]->e->v2;
461
462         if (ulp->flag & ULP_FLIP_0) {
463           SWAP(BMVert *, f_verts[0], f_verts[3]);
464         }
465         if (ulp->flag & ULP_FLIP_1) {
466           SWAP(BMVert *, f_verts[1], f_verts[2]);
467         }
468       }
469       else {
470         /* tri */
471         f_verts[0] = v_shared;
472         f_verts[1] = BM_edge_other_vert(ulp->l_pair[0]->e, v_shared);
473         f_verts[2] = BM_edge_other_vert(ulp->l_pair[1]->e, v_shared);
474         f_verts[3] = NULL;
475
476         /* don't use the flip flags */
477         if (v_shared == ulp->l_pair[0]->v) {
478           SWAP(BMVert *, f_verts[0], f_verts[1]);
479         }
480       }
481
482       /* face should never exist */
483       BLI_assert(!BM_face_exists(f_verts, f_verts[3] ? 4 : 3));
484
485       f = BM_face_create_verts(bm, f_verts, f_verts[3] ? 4 : 3, f_example, BM_CREATE_NOP, true);
486
487       l_iter = BM_FACE_FIRST_LOOP(f);
488
489       if (f_verts[3]) {
490         BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
491         l_iter = l_iter->next;
492         BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
493         l_iter = l_iter->next;
494         BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
495         l_iter = l_iter->next;
496         BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
497       }
498       else {
499         BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
500         l_iter = l_iter->next;
501         BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
502         l_iter = l_iter->next;
503         BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
504       }
505     }
506   }
507 }
508
509 /* --- end 'face-fill' code --- */
510
511 /**
512  * This is the main vert ripping function (rip when one vertex is selected)
513  */
514 static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obedit, bool do_fill)
515 {
516   UnorderedLoopPair *fill_uloop_pairs = NULL;
517   ARegion *ar = CTX_wm_region(C);
518   RegionView3D *rv3d = CTX_wm_region_view3d(C);
519   BMEditMesh *em = BKE_editmesh_from_object(obedit);
520   BMesh *bm = em->bm;
521   BMIter iter, liter;
522   BMLoop *l;
523   BMEdge *e_best;
524   BMVert *v;
525   const int totvert_orig = bm->totvert;
526   int i;
527   float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
528   float dist_sq = FLT_MAX;
529   float d;
530   bool is_wire, is_manifold_region;
531
532   BMEditSelection ese;
533   int totboundary_edge = 0;
534
535   ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
536
537   /* find selected vert - same some time and check history first */
538   if (BM_select_history_active_get(bm, &ese) && ese.htype == BM_VERT) {
539     v = (BMVert *)ese.ele;
540   }
541   else {
542     ese.ele = NULL;
543
544     BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
545       if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
546         break;
547       }
548     }
549   }
550
551   /* (v == NULL) should be impossible */
552   if ((v == NULL) || (v->e == NULL)) {
553     return OPERATOR_CANCELLED;
554   }
555
556   is_wire = BM_vert_is_wire(v);
557   is_manifold_region = BM_vert_is_manifold_region(v);
558
559   e_best = NULL;
560
561   {
562     BMEdge *e;
563     /* find closest edge to mouse cursor */
564     BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
565       /* consider wire as boundary for this purpose,
566        * otherwise we can't a face away from a wire edge */
567       totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e));
568       if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
569         if ((is_manifold_region == false) || BM_edge_is_manifold(e)) {
570           d = edbm_rip_edgedist_squared(
571               ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
572           if ((e_best == NULL) || (d < dist_sq)) {
573             dist_sq = d;
574             e_best = e;
575           }
576         }
577       }
578     }
579   }
580
581   if (e_best && e_best->l && (is_manifold_region == false)) {
582     /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */
583     BMLoop *l_sep = e_best->l->v == v ? e_best->l : e_best->l->next;
584     BMVert *v_new;
585
586     BLI_assert(l_sep->v == v);
587     v_new = BM_face_loop_separate_multi_isolated(bm, l_sep);
588     BLI_assert(BM_vert_find_first_loop(v));
589
590     BM_vert_select_set(bm, v, false);
591     BM_select_history_remove(bm, v);
592
593     BM_vert_select_set(bm, v_new, true);
594     if (ese.ele) {
595       BM_select_history_store(bm, v_new);
596     }
597
598     if (do_fill) {
599       BM_edge_create(bm, v, v_new, NULL, BM_CREATE_NOP);
600     }
601
602     return OPERATOR_FINISHED;
603   }
604
605   /* if we are ripping a single vertex from 3 faces,
606    * then measure the distance to the face corner as well as the edge */
607   if (BM_vert_face_count_is_equal(v, 3) && BM_vert_edge_count_is_equal(v, 3)) {
608     BMEdge *e_all[3];
609     BMLoop *l_all[3];
610     int i1, i2;
611
612     BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3);
613     BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3);
614
615     /* not do a loop similar to the one above, but test against loops */
616     for (i1 = 0; i1 < 3; i1++) {
617       /* consider wire as boundary for this purpose,
618        * otherwise we can't a face away from a wire edge */
619       float l_mid_co[3];
620       l = l_all[i1];
621       edbm_calc_loop_co(l, l_mid_co);
622       d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
623       if ((e_best == NULL) || (d < dist_sq)) {
624         dist_sq = d;
625
626         /* find the edge that is not in this loop */
627         e_best = NULL;
628         for (i2 = 0; i2 < 3; i2++) {
629           if (!BM_edge_in_loop(e_all[i2], l)) {
630             e_best = e_all[i2];
631             break;
632           }
633         }
634         BLI_assert(e_best != NULL);
635       }
636     }
637   }
638
639   /* should we go ahead with edge rip or do we need to do special case, split off vertex?:
640    * split off vertex if...
641    * - we cant find an edge - this means we are ripping a faces vert that is connected to other
642    *   geometry only at the vertex.
643    * - the boundary edge total is greater than 2,
644    *   in this case edge split _can_ work but we get far nicer results if we use this special case.
645    * - there are only 2 edges but we are a wire vert. */
646   if ((is_wire == false && totboundary_edge > 2) || (is_wire == true && totboundary_edge > 1)) {
647     BMVert **vout;
648     int vout_len;
649
650     BM_vert_select_set(bm, v, false);
651
652     bmesh_kernel_vert_separate(bm, v, &vout, &vout_len, true);
653
654     if (vout_len < 2) {
655       MEM_freeN(vout);
656       /* set selection back to avoid active-unselected vertex */
657       BM_vert_select_set(bm, v, true);
658       /* should never happen */
659       return OPERATOR_CANCELLED;
660     }
661     else {
662       int vi_best = 0;
663
664       if (ese.ele) {
665         BM_select_history_remove(bm, ese.ele);
666       }
667
668       dist_sq = FLT_MAX;
669
670       /* in the loop below we find the best vertex to drag based on its connected geometry,
671        * either by its face corner, or connected edge (when no faces are attached) */
672       for (i = 0; i < vout_len; i++) {
673
674         if (BM_vert_is_wire(vout[i]) == false) {
675           /* find the best face corner */
676           BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) {
677             if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
678               float l_mid_co[3];
679
680               edbm_calc_loop_co(l, l_mid_co);
681               d = edbm_rip_edgedist_squared(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT);
682
683               if (d < dist_sq) {
684                 dist_sq = d;
685                 vi_best = i;
686               }
687             }
688           }
689         }
690         else {
691           BMEdge *e;
692           /* a wire vert, find the best edge */
693           BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) {
694             if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
695               float e_mid_co[3];
696
697               mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co);
698               d = edbm_rip_edgedist_squared(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT);
699
700               if (d < dist_sq) {
701                 dist_sq = d;
702                 vi_best = i;
703               }
704             }
705           }
706         }
707       }
708
709       /* vout[0]  == best
710        * vout[1]  == glue
711        * vout[2+] == splice with glue (when vout_len > 2)
712        */
713       if (vi_best != 0) {
714         SWAP(BMVert *, vout[0], vout[vi_best]);
715         vi_best = 0;
716       }
717
718       /* select the vert from the best region */
719       v = vout[vi_best];
720       BM_vert_select_set(bm, v, true);
721
722       if (ese.ele) {
723         BM_select_history_store(bm, v);
724       }
725
726       /* splice all others back together */
727       if (vout_len > 2) {
728         for (i = 2; i < vout_len; i++) {
729           BM_vert_splice(bm, vout[1], vout[i]);
730         }
731       }
732
733       if (do_fill) {
734         /* match extrude vert-order */
735         BM_edge_create(bm, vout[1], vout[0], NULL, BM_CREATE_NOP);
736       }
737
738       MEM_freeN(vout);
739
740       return OPERATOR_FINISHED;
741     }
742   }
743
744   if (!e_best) {
745     return OPERATOR_CANCELLED;
746   }
747
748   /* *** Execute the split! *** */
749   /* unlike edge split, for single vertex split we only use the operator in one of the cases
750    * but both allocate fill */
751
752   {
753     BMVert *v_rip;
754     BMLoop *larr[2];
755     int larr_len = 0;
756
757     /* rip two adjacent edges */
758     if (BM_edge_is_boundary(e_best) || BM_vert_face_count_is_equal(v, 2)) {
759       /* Don't run the edge split operator in this case */
760
761       l = BM_edge_vert_share_loop(e_best->l, v);
762       larr[larr_len] = l;
763       larr_len++;
764
765       /* only tag for face-fill (we don't call the operator) */
766       if (BM_edge_is_boundary(e_best)) {
767         BM_elem_flag_enable(e_best, BM_ELEM_TAG);
768       }
769       else {
770         BM_elem_flag_enable(l->e, BM_ELEM_TAG);
771         BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
772       }
773     }
774     else {
775       if (BM_edge_is_manifold(e_best)) {
776         BMLoop *l_iter, *l_first;
777         l_iter = l_first = e_best->l;
778         do {
779           larr[larr_len] = BM_edge_vert_share_loop(l_iter, v);
780
781           if (do_fill) {
782             /* Only needed when filling...
783              * Also, we never want to tag best edge,
784              * that one won't change during split. See T44618. */
785             if (larr[larr_len]->e == e_best) {
786               BM_elem_flag_enable(larr[larr_len]->prev->e, BM_ELEM_TAG);
787             }
788             else {
789               BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG);
790             }
791           }
792           larr_len++;
793         } while ((l_iter = l_iter->radial_next) != l_first);
794       }
795       else {
796         /* looks like there are no split edges, we could just return/report-error? - Campbell */
797       }
798     }
799
800     /* keep directly before edgesplit */
801     if (do_fill) {
802       fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
803     }
804
805     if (larr_len) {
806       v_rip = BM_face_loop_separate_multi(bm, larr, larr_len);
807     }
808     else {
809       v_rip = NULL;
810     }
811
812     if (v_rip) {
813       BM_vert_select_set(bm, v_rip, true);
814     }
815     else {
816       if (fill_uloop_pairs) {
817         MEM_freeN(fill_uloop_pairs);
818       }
819       return OPERATOR_CANCELLED;
820     }
821   }
822
823   {
824     /* --- select which vert --- */
825     BMVert *v_best = NULL;
826     float l_corner_co[3];
827
828     dist_sq = FLT_MAX;
829     BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
830       if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
831         /* disable by default, re-enable winner at end */
832         BM_vert_select_set(bm, v, false);
833         BM_select_history_remove(bm, v);
834
835         BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
836
837           /* check if v_best is null in the _rare_ case there are numeric issues */
838           edbm_calc_loop_co(l, l_corner_co);
839           d = edbm_rip_edgedist_squared(
840               ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT);
841           if ((v_best == NULL) || (d < dist_sq)) {
842             v_best = v;
843             dist_sq = d;
844           }
845         }
846       }
847     }
848
849     if (v_best) {
850       BM_vert_select_set(bm, v_best, true);
851       if (ese.ele) {
852         BM_select_history_store(bm, v_best);
853       }
854     }
855   }
856
857   if (do_fill && fill_uloop_pairs) {
858     edbm_tagged_loop_pairs_do_fill_faces(bm, fill_uloop_pairs);
859     MEM_freeN(fill_uloop_pairs);
860   }
861
862   if (totvert_orig == bm->totvert) {
863     return OPERATOR_CANCELLED;
864   }
865
866   return OPERATOR_FINISHED;
867 }
868
869 /**
870  * This is the main edge ripping function
871  */
872 static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obedit, bool do_fill)
873 {
874   UnorderedLoopPair *fill_uloop_pairs = NULL;
875   ARegion *ar = CTX_wm_region(C);
876   RegionView3D *rv3d = CTX_wm_region_view3d(C);
877   BMEditMesh *em = BKE_editmesh_from_object(obedit);
878   BMesh *bm = em->bm;
879   BMIter iter, eiter;
880   BMLoop *l;
881   BMEdge *e_best;
882   BMVert *v;
883   const int totedge_orig = bm->totedge;
884   float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
885
886   EdgeLoopPair *eloop_pairs;
887
888   ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat);
889
890   /* important this runs on the original selection, before tampering with tagging */
891   eloop_pairs = edbm_ripsel_looptag_helper(bm);
892
893   /* expand edge selection */
894   BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
895     BMEdge *e;
896     bool all_manifold;
897     int totedge_manifold; /* manifold, visible edges */
898     int i;
899
900     e_best = NULL;
901     i = 0;
902     totedge_manifold = 0;
903     all_manifold = true;
904     BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
905
906       if (!BM_edge_is_wire(e) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
907         /* important to check selection rather then tag here
908          * else we get feedback loop */
909         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
910           e_best = e;
911           i++;
912           /* Tag the edge verts so we know which verts to rip */
913           BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
914           BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
915         }
916         totedge_manifold++;
917       }
918
919       /** #BM_vert_other_disk_edge has no hidden checks so don't check hidden here */
920       if ((all_manifold == true) && (BM_edge_is_manifold(e) == false)) {
921         all_manifold = false;
922       }
923     }
924
925     /* single edge, extend */
926     if (i == 1 && e_best->l) {
927       /* note: if the case of 3 edges has one change in loop stepping,
928        * if this becomes more involved we may be better off splitting
929        * the 3 edge case into its own else-if branch */
930       if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) {
931         BMLoop *l_a = e_best->l;
932         BMLoop *l_b = l_a->radial_next;
933
934         /* find the best face to follow, this way the edge won't point away from
935          * the mouse when there are more than 4 (takes the shortest face fan around) */
936         l = (edbm_rip_edge_side_measure(e_best, l_a, ar, projectMat, fmval) <
937              edbm_rip_edge_side_measure(e_best, l_b, ar, projectMat, fmval)) ?
938                 l_a :
939                 l_b;
940
941         l = BM_loop_other_edge_loop(l, v);
942         /* important edge is manifold else we can be attempting to split off a fan that don't budge,
943          * not crashing but adds duplicate edge. */
944         if (BM_edge_is_manifold(l->e)) {
945           l = l->radial_next;
946
947           if (totedge_manifold != 3) {
948             l = BM_loop_other_edge_loop(l, v);
949           }
950
951           if (l) {
952             BLI_assert(!BM_elem_flag_test(l->e, BM_ELEM_TAG));
953             BM_elem_flag_enable(l->e, BM_ELEM_TAG);
954           }
955         }
956       }
957       else {
958         e = BM_vert_other_disk_edge(v, e_best);
959
960         if (e) {
961           BLI_assert(!BM_elem_flag_test(e, BM_ELEM_TAG));
962           BM_elem_flag_enable(e, BM_ELEM_TAG);
963         }
964       }
965     }
966   }
967
968   /* keep directly before edgesplit */
969   if (do_fill) {
970     fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm);
971   }
972
973   BM_mesh_edgesplit(em->bm, true, true, true);
974
975   /* note: the output of the bmesh operator is ignored, since we built
976    * the contiguous loop pairs to split already, its possible that some
977    * edge did not split even though it was tagged which would not work
978    * as expected (but not crash), however there are checks to ensure
979    * tagged edges will split. So far its not been an issue. */
980   edbm_ripsel_deselect_helper(bm, eloop_pairs, ar, projectMat, fmval);
981   MEM_freeN(eloop_pairs);
982
983   /* deselect loose verts */
984   BM_mesh_select_mode_clean_ex(bm, SCE_SELECT_EDGE);
985
986   if (do_fill && fill_uloop_pairs) {
987     edbm_tagged_loop_pairs_do_fill_faces(bm, fill_uloop_pairs);
988     MEM_freeN(fill_uloop_pairs);
989   }
990
991   if (totedge_orig == bm->totedge) {
992     return OPERATOR_CANCELLED;
993   }
994
995   BM_select_history_validate(bm);
996
997   return OPERATOR_FINISHED;
998 }
999
1000 /* based on mouse cursor position, it defines how is being ripped */
1001 static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1002 {
1003   ViewLayer *view_layer = CTX_data_view_layer(C);
1004   uint objects_len = 0;
1005   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1006       view_layer, CTX_wm_view3d(C), &objects_len);
1007   const bool do_fill = RNA_boolean_get(op->ptr, "use_fill");
1008
1009   bool no_vertex_selected = true;
1010   bool error_face_selected = true;
1011   bool error_disconnected_vertices = true;
1012   bool error_rip_failed = true;
1013
1014   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1015     Object *obedit = objects[ob_index];
1016     BMEditMesh *em = BKE_editmesh_from_object(obedit);
1017
1018     BMesh *bm = em->bm;
1019     BMIter iter;
1020     BMEdge *e;
1021     const bool singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0);
1022     int ret;
1023
1024     if (em->bm->totvertsel == 0) {
1025       continue;
1026     }
1027     no_vertex_selected = false;
1028
1029     /* running in face mode hardly makes sense, so convert to region loop and rip */
1030     if (bm->totfacesel) {
1031       /* highly nifty but hard to support since the operator can fail and we're left
1032        * with modified selection */
1033       // WM_operator_name_call(C, "MESH_OT_region_to_loop", WM_OP_INVOKE_DEFAULT, NULL);
1034       continue;
1035     }
1036     error_face_selected = false;
1037
1038     /* we could support this, but not for now */
1039     if ((bm->totvertsel > 1) && (bm->totedgesel == 0)) {
1040       continue;
1041     }
1042     error_disconnected_vertices = false;
1043
1044     /* note on selection:
1045      * When calling edge split we operate on tagged edges rather then selected
1046      * this is important because the edges to operate on are extended by one,
1047      * but the selection is left alone.
1048      *
1049      * After calling edge split - the duplicated edges have the same selection state as the
1050      * original, so all we do is de-select the far side from the mouse and we have a
1051      * useful selection for grabbing.
1052      */
1053
1054     /* BM_ELEM_SELECT --> BM_ELEM_TAG */
1055     BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
1056       BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT));
1057     }
1058
1059     /* split 2 main parts of this operator out into vertex and edge ripping */
1060     if (singlesel) {
1061       ret = edbm_rip_invoke__vert(C, event, obedit, do_fill);
1062     }
1063     else {
1064       ret = edbm_rip_invoke__edge(C, event, obedit, do_fill);
1065     }
1066
1067     if (ret != OPERATOR_FINISHED) {
1068       continue;
1069     }
1070
1071     BLI_assert(singlesel ? (bm->totvertsel > 0) : (bm->totedgesel > 0));
1072
1073     if (bm->totvertsel == 0) {
1074       continue;
1075     }
1076     error_rip_failed = false;
1077
1078     EDBM_update_generic(em, true, true);
1079   }
1080
1081   MEM_freeN(objects);
1082
1083   if (no_vertex_selected) {
1084     /* Ignore it. */
1085     return OPERATOR_CANCELLED;
1086   }
1087   else if (error_face_selected) {
1088     BKE_report(op->reports, RPT_ERROR, "Cannot rip selected faces");
1089     return OPERATOR_CANCELLED;
1090   }
1091   else if (error_disconnected_vertices) {
1092     BKE_report(op->reports, RPT_ERROR, "Cannot rip multiple disconnected vertices");
1093     return OPERATOR_CANCELLED;
1094   }
1095   else if (error_rip_failed) {
1096     BKE_report(op->reports, RPT_ERROR, "Rip failed");
1097     return OPERATOR_CANCELLED;
1098   }
1099   /* No errors, everything went fine. */
1100   return OPERATOR_FINISHED;
1101 }
1102
1103 void MESH_OT_rip(wmOperatorType *ot)
1104 {
1105   /* identifiers */
1106   ot->name = "Rip";
1107   ot->idname = "MESH_OT_rip";
1108   ot->description = "Disconnect vertex or edges from connected geometry";
1109
1110   /* api callbacks */
1111   ot->invoke = edbm_rip_invoke;
1112   ot->poll = EDBM_view3d_poll;
1113
1114   /* flags */
1115   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1116
1117   /* to give to transform */
1118   Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
1119   RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill the ripped region");
1120 }