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