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