Blender V5.0
editmesh_polybuild.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include <algorithm>
13
14#include "DNA_object_types.h"
15
16#include "BKE_context.hh"
17#include "BKE_editmesh.hh"
18#include "BKE_layer.hh"
19#include "BKE_object_types.hh"
20#include "BKE_screen.hh"
21
22#include "BLI_listbase.h"
23#include "BLI_math_geom.h"
24#include "BLI_math_matrix.h"
25#include "BLI_math_vector.h"
26
27#include "WM_types.hh"
28
29#include "ED_mesh.hh"
30#include "ED_object.hh"
31#include "ED_transform.hh"
32#include "ED_view3d.hh"
33
34#include "bmesh.hh"
35
36#include "mesh_intern.hh" /* own include */
37
38#include "RNA_access.hh"
39#include "RNA_define.hh"
40
41#include "WM_api.hh"
42
43#include "DEG_depsgraph.hh"
44
45using blender::Vector;
46
47/* -------------------------------------------------------------------- */
50
51static void edbm_selectmode_ensure(Scene *scene, BMEditMesh *em, short selectmode)
52{
53 if ((scene->toolsettings->selectmode & selectmode) == 0) {
54 scene->toolsettings->selectmode |= selectmode;
56 }
57}
58
59/* Could make public, for now just keep here. */
60static void edbm_flag_disable_all_multi(const Scene *scene,
61 ViewLayer *view_layer,
62 View3D *v3d,
63 const char hflag)
64{
66 scene, view_layer, v3d);
67 for (Object *ob_iter : objects) {
68 BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
69 BMesh *bm_iter = em_iter->bm;
70 if (bm_iter->totvertsel) {
71 EDBM_flag_disable_all(em_iter, hflag);
72 DEG_id_tag_update(static_cast<ID *>(ob_iter->data), ID_RECALC_SELECT);
73 }
74 }
75}
76
78static bool edbm_preselect_or_active(bContext *C, const View3D *v3d, Base **r_base, BMElem **r_ele)
79{
80 ARegion *region = CTX_wm_region(C);
81 const bool show_gizmo = !(v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL));
82
83 wmGizmoMap *gzmap = show_gizmo ? region->runtime->gizmo_map : nullptr;
84 wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_mesh_preselect_elem") :
85 nullptr;
86
87 if (gzgroup != nullptr) {
88 /* Check the gizmo can draw, if not the state may be stale
89 * or if the gizmo group has never drawn the list may even be empty, see: #141336.
90 *
91 * NOTE(ideasman42): we could also fail with an error in this case,
92 * however that would be quite disruptive, so fallback to the active element. */
94 /* Typically only reached when attempting to use the tool during animation playback. */
95 gzgroup = nullptr;
96 }
97 else if (BLI_listbase_is_empty(&gzgroup->gizmos)) {
98 /* If the gizmo group is drawing it *should* never be empty.
99 * Even so, avoid crashing if it is - investigate if this is ever reached. */
100 BLI_assert(false);
101 gzgroup = nullptr;
102 }
103 }
104
105 if (gzgroup != nullptr) {
106 wmGizmo *gz = static_cast<wmGizmo *>(gzgroup->gizmos.first);
108 }
109 else {
110 const Scene *scene = CTX_data_scene(C);
111 ViewLayer *view_layer = CTX_data_view_layer(C);
112 BKE_view_layer_synced_ensure(scene, view_layer);
113 Base *base = BKE_view_layer_active_base_get(view_layer);
114 Object *obedit = base->object;
116 BMesh *bm = em->bm;
117 *r_base = base;
118 *r_ele = BM_mesh_active_elem_get(bm);
119 }
120 return (*r_ele != nullptr);
121}
122
124 Base **r_base,
125 BMElem **r_ele)
126{
128 bool ok = edbm_preselect_or_active(C, vc.v3d, r_base, r_ele);
129 if (ok) {
130 ED_view3d_viewcontext_init_object(&vc, (*r_base)->object);
131 }
132 return vc;
133}
134
136 wmOperator * /*op*/,
137 const wmEvent * /*event*/)
138{
139 Base *basact = nullptr;
140 BMElem *ele_act = nullptr;
142 BMEditMesh *em = vc.em;
143 BMesh *bm = em->bm;
144
145 invert_m4_m4(vc.obedit->runtime->world_to_object.ptr(), vc.obedit->object_to_world().ptr());
147
148 if (!ele_act) {
149 return OPERATOR_CANCELLED;
150 }
151
153
155
156 if (ele_act->head.htype == BM_VERT) {
157 BM_vert_select_set(bm, (BMVert *)ele_act, true);
158 }
159 if (ele_act->head.htype == BM_EDGE) {
160 BM_edge_select_set(bm, (BMEdge *)ele_act, true);
161 }
162 if (ele_act->head.htype == BM_FACE) {
163 BM_face_select_set(bm, (BMFace *)ele_act, true);
164 }
165
167 params.calc_looptris = true;
168 params.calc_normals = true;
169 params.is_destructive = true;
170 EDBM_update(static_cast<Mesh *>(vc.obedit->data), &params);
171 if (basact != nullptr) {
173 if (BKE_view_layer_active_base_get(vc.view_layer) != basact) {
175 }
176 }
177 BM_select_history_store(bm, ele_act);
179 return OPERATOR_FINISHED;
180}
181
183{
184 /* identifiers */
185 ot->name = "Poly Build Transform at Cursor";
186 ot->idname = "MESH_OT_polybuild_transform_at_cursor";
187
188 /* API callbacks. */
190 ot->poll = EDBM_view3d_poll;
191
192 /* flags */
194
195 /* to give to transform */
197}
198
200 wmOperator *op,
201 const wmEvent * /*event*/)
202{
203 bool changed = false;
204 Base *basact = nullptr;
205 BMElem *ele_act = nullptr;
207 BMEditMesh *em = vc.em;
208 BMesh *bm = em->bm;
209
210 invert_m4_m4(vc.obedit->runtime->world_to_object.ptr(), vc.obedit->object_to_world().ptr());
212
213 if (!ele_act) {
214 return OPERATOR_CANCELLED;
215 }
216
218
219 if (ele_act->head.htype == BM_FACE) {
220 BMFace *f_act = (BMFace *)ele_act;
223 if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_TAG, DEL_FACES)) {
224 return OPERATOR_CANCELLED;
225 }
226 changed = true;
227 }
228 if (ele_act->head.htype == BM_VERT) {
229 BMVert *v_act = (BMVert *)ele_act;
230 if (BM_vert_is_edge_pair(v_act) && !BM_vert_is_wire(v_act)) {
231 BM_edge_collapse(bm, v_act->e, v_act, true, true);
232 changed = true;
233 }
234 else {
237
238 if (!EDBM_op_callf(em,
239 op,
240 "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
242 false,
243 false))
244 {
245 return OPERATOR_CANCELLED;
246 }
247 changed = true;
248 }
249 }
250
251 if (changed) {
253 params.calc_looptris = true;
254 params.calc_normals = true;
255 params.is_destructive = true;
256 EDBM_update(static_cast<Mesh *>(vc.obedit->data), &params);
257 if (basact != nullptr) {
259 if (BKE_view_layer_active_base_get(vc.view_layer) != basact) {
261 }
262 }
264 return OPERATOR_FINISHED;
265 }
266 return OPERATOR_CANCELLED;
267}
268
270{
271 /* identifiers */
272 ot->name = "Poly Build Delete at Cursor";
273 ot->idname = "MESH_OT_polybuild_delete_at_cursor";
274
275 /* API callbacks. */
277 ot->poll = EDBM_view3d_poll;
278
279 /* flags */
281
282 /* to give to transform */
284}
285
287
288/* -------------------------------------------------------------------- */
291
293 wmOperator *op,
294 const wmEvent *event)
295{
296 float center[3];
297 bool changed = false;
298
299 Base *basact = nullptr;
300 BMElem *ele_act = nullptr;
302 BMEditMesh *em = vc.em;
303 BMesh *bm = em->bm;
304
305 invert_m4_m4(vc.obedit->runtime->world_to_object.ptr(), vc.obedit->object_to_world().ptr());
307
309
310 if (ele_act == nullptr || ele_act->head.htype == BM_FACE) {
311 /* Just add vert */
312 copy_v3_v3(center, vc.scene->cursor.location);
313 mul_v3_m4v3(center, vc.obedit->object_to_world().ptr(), center);
314 ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
315 mul_m4_v3(vc.obedit->world_to_object().ptr(), center);
316
317 BMVert *v_new = BM_vert_create(bm, center, nullptr, BM_CREATE_NOP);
319 BM_vert_select_set(bm, v_new, true);
321 changed = true;
322 }
323 else if (ele_act->head.htype == BM_EDGE) {
324 BMEdge *e_act = (BMEdge *)ele_act;
325 BMFace *f_reference = e_act->l ? e_act->l->f : nullptr;
326
327 mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
328 mul_m4_v3(vc.obedit->object_to_world().ptr(), center);
329 ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
330 mul_m4_v3(vc.obedit->world_to_object().ptr(), center);
331 if (f_reference->len == 3 && RNA_boolean_get(op->ptr, "create_quads")) {
332 const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
333 BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, nullptr, std::clamp(fac, 0.0f, 1.0f));
334 copy_v3_v3(v_new->co, center);
336 BM_vert_select_set(bm, v_new, true);
338 }
339 else {
340 BMVert *v_tri[3];
341 v_tri[0] = e_act->v1;
342 v_tri[1] = e_act->v2;
343 v_tri[2] = BM_vert_create(bm, center, nullptr, BM_CREATE_NOP);
344 if (e_act->l && e_act->l->v == v_tri[0]) {
345 std::swap(v_tri[0], v_tri[1]);
346 }
347 BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
349 BM_vert_select_set(bm, v_tri[2], true);
350 BM_select_history_store(bm, v_tri[2]);
351 }
352 changed = true;
353 }
354 else if (ele_act->head.htype == BM_VERT) {
355 BMVert *v_act = (BMVert *)ele_act;
356 BMEdge *e_pair[2] = {nullptr};
357
358 if (v_act->e != nullptr) {
359 for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == nullptr); allow_wire++) {
360 int i = 0;
361 BMEdge *e_iter = v_act->e;
362 do {
363 if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
364 (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
365 {
366 if (i == 2) {
367 e_pair[0] = e_pair[1] = nullptr;
368 break;
369 }
370 e_pair[i++] = e_iter;
371 }
372 } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
373 }
374 }
375
376 if (e_pair[1] != nullptr) {
377 /* Quad from edge pair. */
378 if (BM_edge_calc_length_squared(e_pair[0]) < BM_edge_calc_length_squared(e_pair[1])) {
379 std::swap(e_pair[0], e_pair[1]);
380 }
381
382 BMFace *f_reference = e_pair[0]->l ? e_pair[0]->l->f : nullptr;
383
384 mul_v3_m4v3(center, vc.obedit->object_to_world().ptr(), v_act->co);
385 ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
386 mul_m4_v3(vc.obedit->world_to_object().ptr(), center);
387
388 BMVert *v_quad[4];
389 v_quad[0] = v_act;
390 v_quad[1] = BM_edge_other_vert(e_pair[0], v_act);
391 v_quad[2] = BM_vert_create(bm, center, nullptr, BM_CREATE_NOP);
392 v_quad[3] = BM_edge_other_vert(e_pair[1], v_act);
393 if (e_pair[0]->l && e_pair[0]->l->v == v_quad[0]) {
394 std::swap(v_quad[1], v_quad[3]);
395 }
396 // BMFace *f_new =
397 BM_face_create_verts(bm, v_quad, 4, f_reference, BM_CREATE_NOP, true);
398
400 BM_vert_select_set(bm, v_quad[2], true);
401 BM_select_history_store(bm, v_quad[2]);
402 changed = true;
403 }
404 else {
405 /* Just add edge */
406 mul_m4_v3(vc.obedit->object_to_world().ptr(), center);
407 ED_view3d_win_to_3d_int(vc.v3d, vc.region, v_act->co, event->mval, center);
408 mul_m4_v3(vc.obedit->world_to_object().ptr(), center);
409
410 BMVert *v_new = BM_vert_create(bm, center, nullptr, BM_CREATE_NOP);
411
412 BM_edge_create(bm, v_act, v_new, nullptr, BM_CREATE_NOP);
413
414 BM_vert_select_set(bm, v_new, true);
416 changed = true;
417 }
418 }
419
420 if (changed) {
422 params.calc_looptris = true;
423 params.calc_normals = true;
424 params.is_destructive = true;
425 EDBM_update(static_cast<Mesh *>(vc.obedit->data), &params);
426
427 if (basact != nullptr) {
429 if (BKE_view_layer_active_base_get(vc.view_layer) != basact) {
431 }
432 }
433
435
436 return OPERATOR_FINISHED;
437 }
438 return OPERATOR_CANCELLED;
439}
440
442{
443 /* identifiers */
444 ot->name = "Poly Build Face at Cursor";
445 ot->idname = "MESH_OT_polybuild_face_at_cursor";
446
447 /* API callbacks. */
449 ot->poll = EDBM_view3d_poll;
450
451 /* flags */
453
454 RNA_def_boolean(ot->srna,
455 "create_quads",
456 true,
457 "Create Quads",
458 "Automatically split edges in triangles to maintain quad topology");
459 /* to give to transform */
461}
462
464
465/* -------------------------------------------------------------------- */
468
470 wmOperator * /*op*/,
471 const wmEvent *event)
472{
473 float center[3];
474 bool changed = false;
475
476 Base *basact = nullptr;
477 BMElem *ele_act = nullptr;
479 BMEditMesh *em = vc.em;
480 BMesh *bm = em->bm;
481
482 invert_m4_m4(vc.obedit->runtime->world_to_object.ptr(), vc.obedit->object_to_world().ptr());
484
486
487 if (ele_act == nullptr || ele_act->head.hflag == BM_FACE) {
489 }
490 if (ele_act->head.htype == BM_EDGE) {
491 BMEdge *e_act = (BMEdge *)ele_act;
492 mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co);
493 mul_m4_v3(vc.obedit->object_to_world().ptr(), center);
494 ED_view3d_win_to_3d_int(vc.v3d, vc.region, center, event->mval, center);
495 mul_m4_v3(vc.obedit->world_to_object().ptr(), center);
496
497 const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
498 BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, nullptr, std::clamp(fac, 0.0f, 1.0f));
499 copy_v3_v3(v_new->co, center);
500
502 BM_vert_select_set(bm, v_new, true);
504 changed = true;
505 }
506 else if (ele_act->head.htype == BM_VERT) {
507 /* Just do nothing, allow dragging. */
508 return OPERATOR_FINISHED;
509 }
510
511 if (changed) {
513 params.calc_looptris = true;
514 params.calc_normals = true;
515 params.is_destructive = true;
516 EDBM_update(static_cast<Mesh *>(vc.obedit->data), &params);
517
519
521 if (BKE_view_layer_active_base_get(vc.view_layer) != basact) {
523 }
524
525 return OPERATOR_FINISHED;
526 }
527 return OPERATOR_CANCELLED;
528}
529
531{
532 /* identifiers */
533 ot->name = "Poly Build Split at Cursor";
534 ot->idname = "MESH_OT_polybuild_split_at_cursor";
535
536 /* API callbacks. */
538 ot->poll = EDBM_view3d_poll;
539
540 /* flags */
542
543 /* to give to transform */
545}
546
548
549/* -------------------------------------------------------------------- */
552
554 wmOperator *op,
555 const wmEvent * /*event*/)
556{
557 bool changed = false;
558
559 Base *basact = nullptr;
560 BMElem *ele_act = nullptr;
562 BMEditMesh *em = vc.em;
563 BMesh *bm = em->bm;
564
565 if (ele_act == nullptr) {
566 /* pass */
567 }
568 else if (ele_act->head.htype == BM_EDGE) {
569 BMEdge *e_act = (BMEdge *)ele_act;
570 BMLoop *l_a, *l_b;
571 if (BM_edge_loop_pair(e_act, &l_a, &l_b)) {
572 BMFace *f_double;
573 BMFace *f_new = BM_faces_join_pair(bm, l_a, l_b, true, &f_double);
574 /* See #BM_faces_join note on callers asserting when `r_double` is non-null. */
575 BLI_assert_msg(f_double == nullptr,
576 "Doubled face detected at " AT ". Resulting mesh may be corrupt.");
577
578 if (f_new) {
579 changed = true;
580 }
581 }
582 }
583 else if (ele_act->head.htype == BM_VERT) {
584 BMVert *v_act = (BMVert *)ele_act;
585 if (BM_vert_is_edge_pair(v_act)) {
586 BM_edge_collapse(bm, v_act->e, v_act, true, true);
587 }
588 else {
589 /* too involved to do inline */
590
591 /* Avoid using selection so failure won't leave modified state. */
594
595 if (!EDBM_op_callf(em,
596 op,
597 "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
599 false,
600 false))
601 {
602 return OPERATOR_CANCELLED;
603 }
604 }
605 changed = true;
606 }
607
608 if (changed) {
610
612 EDBM_update(static_cast<Mesh *>(vc.obedit->data), &params);
613
615 if (BKE_view_layer_active_base_get(vc.view_layer) != basact) {
617 }
618
620
621 return OPERATOR_FINISHED;
622 }
623 return OPERATOR_CANCELLED;
624}
625
627{
628 /* identifiers */
629 ot->name = "Poly Build Dissolve at Cursor";
630 ot->idname = "MESH_OT_polybuild_dissolve_at_cursor";
631
632 /* API callbacks. */
634 ot->poll = EDBM_view3d_poll;
635
636 /* flags */
638}
639
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_active_base_get(ViewLayer *view_layer)
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
void mul_m4_v3(const float M[4][4], float r[3])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
unsigned int uint
#define AT
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
Object is a sort of wrapper for general info.
@ SCE_SELECT_VERTEX
@ V3D_GIZMO_HIDE_TOOL
@ V3D_GIZMO_HIDE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
void EDBM_flag_disable_all(BMEditMesh *em, char hflag)
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params)
void EDBM_selectmode_set(BMEditMesh *em, short selectmode)
ViewContext em_setup_viewcontext(bContext *C)
#define P_PROPORTIONAL
#define P_MIRROR_DUMMY
void ED_view3d_gizmo_mesh_preselect_get_active(const bContext *C, const wmGizmo *gz, Base **r_base, BMElem **r_ele)
void ED_view3d_win_to_3d_int(const View3D *v3d, const ARegion *region, const float depth_pt[3], const int mval[2], float r_out[3])
void ED_view3d_init_mats_rv3d(const Object *ob, RegionView3D *rv3d)
void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
#define C
Definition RandGen.cpp:29
@ WM_GIZMOMAP_DRAWSTEP_3D
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define BM_DISK_EDGE_NEXT(e, v)
@ BM_ELEM_HIDDEN
@ BM_ELEM_SELECT
@ BM_ELEM_TAG
BMFace * BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
Definition bmesh_core.cc:41
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
@ BM_CREATE_NOP
Definition bmesh_core.hh:28
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
BMesh * bm
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
Select Face.
BMElem * BM_mesh_active_elem_get(BMesh *bm)
void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
Select Vert.
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
Select Edge.
#define BM_select_history_store(bm, ele)
BMVert * BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
Edge Split.
BMFace * BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_del, BMFace **r_double)
Faces Join Pair.
BMVert * BM_edge_collapse(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces)
#define BM_FACE
#define BM_EDGE
#define BM_VERT
bool BM_vert_is_wire(const BMVert *v)
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
float BM_edge_calc_length_squared(const BMEdge *e)
bool BM_vert_is_edge_pair(const BMVert *v)
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
static wmOperatorStatus edbm_polybuild_transform_at_cursor_invoke(bContext *C, wmOperator *, const wmEvent *)
static wmOperatorStatus edbm_polybuild_split_at_cursor_invoke(bContext *C, wmOperator *, const wmEvent *event)
static bool edbm_preselect_or_active(bContext *C, const View3D *v3d, Base **r_base, BMElem **r_ele)
void MESH_OT_polybuild_transform_at_cursor(wmOperatorType *ot)
static void edbm_flag_disable_all_multi(const Scene *scene, ViewLayer *view_layer, View3D *v3d, const char hflag)
static ViewContext edbm_preselect_or_active_init_viewcontext(bContext *C, Base **r_base, BMElem **r_ele)
void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot)
static void edbm_selectmode_ensure(Scene *scene, BMEditMesh *em, short selectmode)
static wmOperatorStatus edbm_polybuild_delete_at_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *)
static wmOperatorStatus edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void MESH_OT_polybuild_delete_at_cursor(wmOperatorType *ot)
void MESH_OT_polybuild_dissolve_at_cursor(wmOperatorType *ot)
void MESH_OT_polybuild_split_at_cursor(wmOperatorType *ot)
static wmOperatorStatus edbm_polybuild_dissolve_at_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *)
bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt,...)
bool EDBM_view3d_poll(bContext *C)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void base_activate(bContext *C, Base *base)
void properties_register(wmOperatorType *ot, int flags)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
ARegionRuntimeHandle * runtime
BMVert * v1
BMVert * v2
struct BMLoop * l
BMHeader head
struct BMVert * v
struct BMFace * f
float co[3]
struct BMEdge * e
int totvertsel
struct Object * object
Definition DNA_ID.h:414
void * first
ObjectRuntimeHandle * runtime
struct ToolSettings * toolsettings
View3DCursor cursor
RegionView3D * rv3d
Definition ED_view3d.hh:80
ARegion * region
Definition ED_view3d.hh:77
Scene * scene
Definition ED_view3d.hh:73
BMEditMesh * em
Definition ED_view3d.hh:81
wmWindow * win
Definition ED_view3d.hh:79
ViewLayer * view_layer
Definition ED_view3d.hh:74
View3D * v3d
Definition ED_view3d.hh:78
Object * obedit
Definition ED_view3d.hh:76
int mval[2]
Definition WM_types.hh:763
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_event_add_mousemove(wmWindow *win)
wmOperatorType * ot
Definition wm_files.cc:4237
bool WM_gizmo_context_check_drawstep(const bContext *C, eWM_GizmoFlagMapDrawStep step)
Definition wm_gizmo.cc:728
wmGizmoGroup * WM_gizmomap_group_find(wmGizmoMap *gzmap, const char *idname)