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