Merge branch 'blender2.7'
[blender.git] / source / blender / editors / mesh / editmesh_polybuild.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup edmesh
19  *
20  * Tools to implement polygon building tool,
21  * an experimental tool for quickly constructing/manipulating faces.
22  */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "DNA_object_types.h"
27
28 #include "BLI_math.h"
29
30 #include "BKE_context.h"
31 #include "BKE_report.h"
32 #include "BKE_editmesh.h"
33 #include "BKE_mesh.h"
34 #include "BKE_layer.h"
35
36 #include "WM_types.h"
37
38 #include "ED_object.h"
39 #include "ED_mesh.h"
40 #include "ED_scene.h"
41 #include "ED_screen.h"
42 #include "ED_transform.h"
43 #include "ED_view3d.h"
44
45 #include "bmesh.h"
46
47 #include "mesh_intern.h"  /* own include */
48
49 #include "RNA_access.h"
50 #include "RNA_define.h"
51
52 #include "WM_api.h"
53
54 #include "DEG_depsgraph.h"
55
56 /* -------------------------------------------------------------------- */
57 /** \name Local Utilities
58  * \{ */
59
60 static void edbm_selectmode_ensure(Scene *scene, BMEditMesh *em, short selectmode)
61 {
62         if ((scene->toolsettings->selectmode & selectmode) == 0) {
63                 scene->toolsettings->selectmode |= selectmode;
64                 em->selectmode = scene->toolsettings->selectmode;
65                 EDBM_selectmode_set(em);
66         }
67 }
68
69 /* Could make public, for now just keep here. */
70 static void edbm_flag_disable_all_multi(ViewLayer *view_layer, View3D *v3d, const char hflag)
71 {
72         uint objects_len = 0;
73         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, &objects_len);
74         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
75                 Object *ob_iter = objects[ob_index];
76                 BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
77                 BMesh *bm_iter = em_iter->bm;
78                 if (bm_iter->totvertsel) {
79                         EDBM_flag_disable_all(em_iter, hflag);
80                         DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
81                 }
82         }
83         MEM_freeN(objects);
84 }
85
86 /* When accessed as a tool, get the active edge from the preselection gizmo. */
87 static bool edbm_preselect_or_active(
88         bContext *C,
89         Base **r_base,
90         BMElem **r_ele)
91 {
92         ViewLayer *view_layer = CTX_data_view_layer(C);
93         ARegion *ar = CTX_wm_region(C);
94         wmGizmoMap *gzmap = ar->gizmo_map;
95         wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_mesh_preselect_elem") : NULL;
96         if (gzgroup != NULL) {
97                 wmGizmo *gz = gzgroup->gizmos.first;
98                 const int object_index = RNA_int_get(gz->ptr, "object_index");
99
100                 /* weak, allocate an array just to access the index. */
101                 Base *base = NULL;
102                 Object *obedit = NULL;
103                 {
104                         uint bases_len;
105                         Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, CTX_wm_view3d(C), &bases_len);
106                         if (object_index < bases_len) {
107                                 base = bases[object_index];
108                                 obedit = base->object;
109                         }
110                         MEM_freeN(bases);
111                 }
112
113                 *r_base = base;
114                 *r_ele = NULL;
115
116                 if (obedit) {
117                         BMEditMesh *em = BKE_editmesh_from_object(obedit);
118                         BMesh *bm = em->bm;
119                         const int vert_index = RNA_int_get(gz->ptr, "vert_index");
120                         const int edge_index = RNA_int_get(gz->ptr, "edge_index");
121                         const int face_index = RNA_int_get(gz->ptr, "face_index");
122                         if (vert_index != -1) {
123                                 *r_ele = (BMElem *)BM_vert_at_index_find(bm, vert_index);
124                         }
125                         else if (edge_index != -1) {
126                                 *r_ele = (BMElem *)BM_edge_at_index_find(bm, edge_index);
127                         }
128                         else if (face_index != -1) {
129                                 *r_ele = (BMElem *)BM_face_at_index_find(bm, face_index);
130                         }
131                 }
132         }
133         else {
134                 Base *base = view_layer->basact;
135                 Object *obedit = base->object;
136                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
137                 BMesh *bm = em->bm;
138                 *r_base = base;
139                 *r_ele = BM_mesh_active_elem_get(bm);
140         }
141         return (*r_ele != NULL);
142 }
143
144 static bool edbm_preselect_or_active_init_viewcontext(
145         bContext *C,
146         ViewContext *vc,
147         Base **r_base,
148         BMElem **r_ele)
149 {
150         em_setup_viewcontext(C, vc);
151         bool ok = edbm_preselect_or_active(C, r_base, r_ele);
152         if (ok) {
153                 ED_view3d_viewcontext_init_object(vc, (*r_base)->object);
154         }
155         return ok;
156 }
157
158 /** \} */
159
160 /* -------------------------------------------------------------------- */
161 /** \name Face at Cursor
162  * \{ */
163
164 static int edbm_polybuild_face_at_cursor_invoke(
165         bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
166 {
167         float center[3];
168         bool changed = false;
169
170         ViewContext vc;
171         Base *basact = NULL;
172         BMElem *ele_act = NULL;
173         edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
174         BMEditMesh *em = vc.em;
175         BMesh *bm = em->bm;
176
177         invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
178         ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
179
180         edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
181
182         if (ele_act == NULL || ele_act->head.htype == BM_FACE) {
183                 /* Just add vert */
184                 copy_v3_v3(center, vc.scene->cursor.location);
185                 mul_v3_m4v3(center, vc.obedit->obmat, center);
186                 ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
187                 mul_m4_v3(vc.obedit->imat, center);
188
189                 BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
190                 edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
191                 BM_vert_select_set(bm, v_new, true);
192                 BM_select_history_store(bm, v_new);
193                 changed = true;
194         }
195         else if (ele_act->head.htype == BM_EDGE) {
196                 BMEdge *e_act = (BMEdge *)ele_act;
197                 BMFace *f_reference = e_act->l ? e_act->l->f : NULL;
198
199                 mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
200                 mul_m4_v3(vc.obedit->obmat, center);
201                 ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
202                 mul_m4_v3(vc.obedit->imat, center);
203
204                 BMVert *v_tri[3];
205                 v_tri[0] = e_act->v1;
206                 v_tri[1] = e_act->v2;
207                 v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
208                 if (e_act->l && e_act->l->v == v_tri[0]) {
209                         SWAP(BMVert *, v_tri[0], v_tri[1]);
210                 }
211                 // BMFace *f_new =
212                 BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
213
214                 edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
215                 BM_vert_select_set(bm, v_tri[2], true);
216                 BM_select_history_store(bm, v_tri[2]);
217                 changed = true;
218         }
219         else if (ele_act->head.htype == BM_VERT) {
220                 BMVert *v_act = (BMVert *)ele_act;
221                 BMEdge *e_pair[2] = {NULL};
222
223                 if (v_act->e != NULL) {
224                         for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) {
225                                 int i = 0;
226                                 BMEdge *e_iter = v_act->e;
227                                 do {
228                                         if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
229                                             (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
230                                         {
231                                                 if (i == 2) {
232                                                         e_pair[0] = e_pair[1] = NULL;
233                                                         break;
234                                                 }
235                                                 e_pair[i++] = e_iter;
236                                         }
237                                 } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
238                         }
239                 }
240
241                 if (e_pair[1] != NULL) {
242                         /* Quad from edge pair. */
243                         if (BM_edge_calc_length_squared(e_pair[0]) <
244                             BM_edge_calc_length_squared(e_pair[1]))
245                         {
246                                 SWAP(BMEdge *, e_pair[0], e_pair[1]);
247                         }
248
249                         BMFace *f_reference = e_pair[0]->l ? e_pair[0]->l->f : NULL;
250
251                         mul_v3_m4v3(center, vc.obedit->obmat, v_act->co);
252                         ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
253                         mul_m4_v3(vc.obedit->imat, center);
254
255                         BMVert *v_quad[4];
256                         v_quad[0] = v_act;
257                         v_quad[1] = BM_edge_other_vert(e_pair[0], v_act);
258                         v_quad[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
259                         v_quad[3] = BM_edge_other_vert(e_pair[1], v_act);
260                         if (e_pair[0]->l && e_pair[0]->l->v == v_quad[0]) {
261                                 SWAP(BMVert *, v_quad[1], v_quad[3]);
262                         }
263                         // BMFace *f_new =
264                         BM_face_create_verts(bm, v_quad, 4, f_reference, BM_CREATE_NOP, true);
265
266                         edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
267                         BM_vert_select_set(bm, v_quad[2], true);
268                         BM_select_history_store(bm, v_quad[2]);
269                         changed = true;
270                 }
271                 else {
272                         /* Just add edge */
273                         mul_m4_v3(vc.obedit->obmat, center);
274                         ED_view3d_win_to_3d_int(vc.v3d, vc.ar, v_act->co, event->mval, center);
275                         mul_m4_v3(vc.obedit->imat, center);
276
277                         BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
278
279                         BM_edge_create(bm, v_act, v_new, NULL, BM_CREATE_NOP);
280
281                         BM_vert_select_set(bm, v_new, true);
282                         BM_select_history_store(bm, v_new);
283                         changed = true;
284                 }
285         }
286
287         if (changed) {
288                 EDBM_mesh_normals_update(em);
289                 EDBM_update_generic(em, true, true);
290
291                 if (basact != NULL) {
292                         if (vc.view_layer->basact != basact) {
293                                 ED_object_base_activate(C, basact);
294                         }
295                 }
296
297                 WM_event_add_mousemove(C);
298
299                 return OPERATOR_FINISHED;
300         }
301         else {
302                 return OPERATOR_CANCELLED;
303         }
304 }
305
306 void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot)
307 {
308         /* identifiers */
309         ot->name = "Poly Build Face at Cursor";
310         ot->idname = "MESH_OT_polybuild_face_at_cursor";
311
312         /* api callbacks */
313         ot->invoke = edbm_polybuild_face_at_cursor_invoke;
314         ot->poll = EDBM_view3d_poll;
315
316         /* flags */
317         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
318
319         /* to give to transform */
320         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
321 }
322
323 /** \} */
324
325 /* -------------------------------------------------------------------- */
326 /** \name Split at Cursor
327  * \{ */
328
329 static int edbm_polybuild_split_at_cursor_invoke(
330         bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
331 {
332         float center[3];
333         bool changed = false;
334
335         ViewContext vc;
336         Base *basact = NULL;
337         BMElem *ele_act = NULL;
338         edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
339         BMEditMesh *em = vc.em;
340         BMesh *bm = em->bm;
341
342         invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
343         ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
344
345         edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
346
347         if (ele_act == NULL || ele_act->head.hflag == BM_FACE) {
348                 return OPERATOR_PASS_THROUGH;
349         }
350         else if (ele_act->head.htype == BM_EDGE) {
351                 BMEdge *e_act = (BMEdge *)ele_act;
352                 mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
353                 mul_m4_v3(vc.obedit->obmat, center);
354                 ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
355                 mul_m4_v3(vc.obedit->imat, center);
356
357                 const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
358                 BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f));
359                 copy_v3_v3(v_new->co, center);
360
361                 edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
362                 BM_vert_select_set(bm, v_new, true);
363                 BM_select_history_store(bm, v_new);
364                 changed = true;
365         }
366         else if (ele_act->head.htype == BM_VERT) {
367                 /* Just do nothing, allow dragging. */
368                 return OPERATOR_FINISHED;
369         }
370
371         if (changed) {
372                 EDBM_mesh_normals_update(em);
373                 EDBM_update_generic(em, true, true);
374
375                 WM_event_add_mousemove(C);
376
377                 if (vc.view_layer->basact != basact) {
378                         ED_object_base_activate(C, basact);
379                 }
380
381                 return OPERATOR_FINISHED;
382         }
383         else {
384                 return OPERATOR_CANCELLED;
385         }
386 }
387
388 void MESH_OT_polybuild_split_at_cursor(wmOperatorType *ot)
389 {
390         /* identifiers */
391         ot->name = "Poly Build Split at Cursor";
392         ot->idname = "MESH_OT_polybuild_split_at_cursor";
393
394         /* api callbacks */
395         ot->invoke = edbm_polybuild_split_at_cursor_invoke;
396         ot->poll = EDBM_view3d_poll;
397
398         /* flags */
399         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
400
401         /* to give to transform */
402         Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
403 }
404
405 /** \} */
406
407
408 /* -------------------------------------------------------------------- */
409 /** \name Dissolve at Cursor
410  *
411  * \{ */
412
413 static int edbm_polybuild_dissolve_at_cursor_invoke(
414         bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
415 {
416         bool changed = false;
417
418         ViewContext vc;
419         Base *basact = NULL;
420         BMElem *ele_act = NULL;
421         edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
422         BMEditMesh *em = vc.em;
423         BMesh *bm = em->bm;
424
425         if (ele_act == NULL) {
426                 /* pass */
427         }
428         else if (ele_act->head.htype == BM_EDGE) {
429                 BMEdge *e_act = (BMEdge *)ele_act;
430                 BMLoop *l_a, *l_b;
431                 if (BM_edge_loop_pair(e_act, &l_a, &l_b)) {
432                         BMFace *f_new = BM_faces_join_pair(bm, l_a, l_b, true);
433                         if (f_new) {
434                                 changed = true;
435                         }
436                 }
437         }
438         else if (ele_act->head.htype == BM_VERT) {
439                 BMVert *v_act = (BMVert *)ele_act;
440                 if (BM_vert_is_edge_pair(v_act)) {
441                         BM_edge_collapse(
442                                 bm, v_act->e, v_act,
443                                 true, true);
444                 }
445                 else {
446                         /* too involved to do inline */
447
448                         /* Avoid using selection so failure wont leave modified state. */
449                         EDBM_flag_disable_all(em, BM_ELEM_TAG);
450                         BM_elem_flag_enable(v_act, BM_ELEM_TAG);
451
452                         if (!EDBM_op_callf(em, op,
453                                            "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
454                                            BM_ELEM_TAG, false, false))
455                         {
456                                 return OPERATOR_CANCELLED;
457                         }
458                 }
459                 changed = true;
460         }
461
462         if (changed) {
463                 edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
464
465                 EDBM_mesh_normals_update(em);
466                 EDBM_update_generic(em, true, true);
467
468                 if (vc.view_layer->basact != basact) {
469                         ED_object_base_activate(C, basact);
470                 }
471
472                 WM_event_add_mousemove(C);
473
474                 return OPERATOR_FINISHED;
475         }
476         else {
477                 return OPERATOR_CANCELLED;
478         }
479 }
480
481 void MESH_OT_polybuild_dissolve_at_cursor(wmOperatorType *ot)
482 {
483         /* identifiers */
484         ot->name = "Poly Build Dissolve at Cursor";
485         ot->idname = "MESH_OT_polybuild_dissolve_at_cursor";
486
487         /* api callbacks */
488         ot->invoke = edbm_polybuild_dissolve_at_cursor_invoke;
489         ot->poll = EDBM_view3d_poll;
490
491         /* flags */
492         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
493 }
494
495 /** \} */