Blender V4.5
editmesh_loopcut.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "DNA_object_types.h"
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_math_vector.h"
14#include "BLI_string.h"
15
16#include "BLT_translation.hh"
17
18#include "BKE_context.hh"
19#include "BKE_editmesh.hh"
20#include "BKE_layer.hh"
21#include "BKE_modifier.hh"
22#include "BKE_report.hh"
23#include "BKE_screen.hh"
24#include "BKE_unit.hh"
25
26#include "UI_interface.hh"
27
28#include "ED_mesh.hh"
29#include "ED_numinput.hh"
30#include "ED_screen.hh"
31#include "ED_space_api.hh"
32#include "ED_view3d.hh"
33
34#include "RNA_access.hh"
35#include "RNA_define.hh"
36#include "RNA_enum_types.hh"
37
38#include "WM_api.hh"
39#include "WM_types.hh"
40
41#include "DEG_depsgraph.hh"
43
44#include "mesh_intern.hh" /* own include */
45
46using blender::Array;
47using blender::float3;
48using blender::Span;
49using blender::Vector;
50
51#define SUBD_SMOOTH_MAX 4.0f
52#define SUBD_CUTS_MAX 500
53
54/* ringsel operator */
55
61
62/* struct for properties used while drawing */
64 ARegion *region; /* region that ringsel was activated in */
65 void *draw_handle; /* for drawing preview loop */
66
68
70
71 Depsgraph *depsgraph;
72
74
76
77 /* These values switch objects based on the object under the cursor. */
82
84
85 bool extend;
86 bool do_cut;
87
88 float cuts; /* cuts as float so smooth mouse pan works in small increments */
90};
91
92/* modal loop selection drawing callback */
93static void ringsel_draw(const bContext * /*C*/, ARegion * /*region*/, void *arg)
94{
95 RingSelOpData *lcd = static_cast<RingSelOpData *>(arg);
96 if (lcd->ob != nullptr) {
97 EDBM_preselect_edgering_draw(lcd->presel_edgering, lcd->ob->object_to_world().ptr());
98 }
99}
100
102{
103 if (!lcd->eed) {
104 return;
105 }
106
107 if (!lcd->extend) {
108 for (Base *base : lcd->bases) {
109 Object *ob_iter = base->object;
112 DEG_id_tag_update(static_cast<ID *>(ob_iter->data), ID_RECALC_SELECT);
114 }
115 }
116
117 BMEditMesh *em = lcd->em;
118 BMEdge *eed_start = lcd->eed;
119 BMWalker walker;
120 BMEdge *eed;
121 BMW_init(&walker,
122 em->bm,
129
130 for (eed = static_cast<BMEdge *>(BMW_begin(&walker, eed_start)); eed;
131 eed = static_cast<BMEdge *>(BMW_step(&walker)))
132 {
133 BM_edge_select_set(em->bm, eed, true);
134 }
135 BMW_end(&walker);
136}
137
138static void ringsel_find_edge(RingSelOpData *lcd, const int previewlines)
139{
140 if (lcd->eed) {
141 MeshCoordsCache *gcache = &lcd->geom_cache[lcd->base_index];
142 if (gcache->is_init == false) {
143 Scene *scene_eval = DEG_get_evaluated(lcd->vc.depsgraph, lcd->vc.scene);
144 Object *ob_eval = DEG_get_evaluated(lcd->vc.depsgraph, lcd->ob);
145 BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval);
147 lcd->vc.depsgraph, em_eval, scene_eval, ob_eval, gcache->allocated_vert_positions);
148 gcache->is_init = true;
149 }
150
152 lcd->presel_edgering, lcd->em->bm, lcd->eed, previewlines, gcache->vert_positions);
153 }
154 else {
156 }
157}
158
160{
161 RingSelOpData *lcd = static_cast<RingSelOpData *>(op->customdata);
162 const int cuts = RNA_int_get(op->ptr, "number_cuts");
163 const float smoothness = RNA_float_get(op->ptr, "smoothness");
164 const int smooth_falloff = RNA_enum_get(op->ptr, "falloff");
165#ifdef BMW_EDGERING_NGON
166 const bool use_only_quads = false;
167#else
168 const bool use_only_quads = false;
169#endif
170
171 if (lcd->eed) {
172 BMEditMesh *em = lcd->em;
173 BMVert *v_eed_orig[2] = {lcd->eed->v1, lcd->eed->v2};
174
175 edgering_select(lcd);
176
177 if (lcd->do_cut) {
178 const bool is_macro = (op->opm != nullptr);
179 /* a single edge (rare, but better support) */
180 const bool is_edge_wire = BM_edge_is_wire(lcd->eed);
181 const bool is_single = is_edge_wire || !BM_edge_is_any_face_len_test(lcd->eed, 4);
182 const int seltype = is_edge_wire ? SUBDIV_SELECT_INNER :
183 is_single ? SUBDIV_SELECT_NONE :
185
186 /* Enable grid-fill, so that intersecting loop-cut works as one would expect.
187 * Note though that it will break edge-slide in this specific case.
188 * See #31939. */
191 smoothness,
192 smooth_falloff,
193 true,
194 0.0f,
195 0.0f,
196 cuts,
197 seltype,
199 0,
200 true,
201 use_only_quads,
202 0);
203
204 /* When used in a macro the tessellation will be recalculated anyway,
205 * this is needed here because modifiers depend on updated tessellation, see #45920 */
207 params.calc_looptris = true;
208 params.calc_normals = false;
209 params.is_destructive = true;
210 EDBM_update(static_cast<Mesh *>(lcd->ob->data), &params);
211
212 if (is_single) {
213 /* de-select endpoints */
214 BM_vert_select_set(em->bm, v_eed_orig[0], false);
215 BM_vert_select_set(em->bm, v_eed_orig[1], false);
216
218 }
219 /* We can't slide multiple edges in vertex select mode, force edge select mode. Do this for
220 * all meshes in multi-object editmode so their selectmode is in sync for following
221 * operators. */
222 else if (is_macro && (cuts > 1) && (em->selectmode & SCE_SELECT_VERTEX)) {
224 }
225 /* Force edge slide to edge select mode in face select mode. Do this for all meshes in
226 * multi-object editmode so their selectmode is in sync for following operators. */
228 /* pass, the change will flush selection */
229 }
230 else {
231 /* else flush explicitly */
233 }
234 }
235 else {
236 /* XXX Is this piece of code ever used now? Simple loop select is now
237 * in editmesh_select.cc (around line 1000)... */
238 /* sets as active, useful for other tools */
239 if (em->selectmode & SCE_SELECT_VERTEX) {
240 /* low priority TODO: get vertex close to mouse. */
241 BM_select_history_store(em->bm, lcd->eed->v1);
242 }
243 if (em->selectmode & SCE_SELECT_EDGE) {
244 BM_select_history_store(em->bm, lcd->eed);
245 }
246
248 DEG_id_tag_update(static_cast<ID *>(lcd->ob->data), ID_RECALC_SELECT);
250 }
251 }
252}
253
254/* called when modal loop selection is done... */
255static void ringsel_exit(bContext * /*C*/, wmOperator *op)
256{
257 RingSelOpData *lcd = static_cast<RingSelOpData *>(op->customdata);
258
259 /* deactivate the extra drawing stuff in 3D-View */
261
263
265
266 MEM_delete(lcd);
267 op->customdata = nullptr;
268}
269
270/* called when modal loop selection gets set up... */
271static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
272{
273 Scene *scene = CTX_data_scene(C);
274
275 /* alloc new customdata */
276 RingSelOpData *lcd = MEM_new<RingSelOpData>(__func__);
277 op->customdata = lcd;
278 lcd->vc = em_setup_viewcontext(C);
279
281
282 /* assign the drawing handle for drawing preview line... */
283 lcd->region = CTX_wm_region(C);
287 /* Initialize once the cursor is over a mesh. */
288 lcd->ob = nullptr;
289 lcd->em = nullptr;
290 lcd->extend = do_cut ? false : RNA_boolean_get(op->ptr, "extend");
291 lcd->do_cut = do_cut;
292 lcd->cuts = RNA_int_get(op->ptr, "number_cuts");
293 lcd->smoothness = RNA_float_get(op->ptr, "smoothness");
294
295 initNumInput(&lcd->num);
296 lcd->num.idx_max = 1;
298 /* No specific flags for smoothness. */
299 lcd->num.unit_sys = scene->unit.system;
300 lcd->num.unit_type[0] = B_UNIT_NONE;
301 lcd->num.unit_type[1] = B_UNIT_NONE;
302
304
305 return 1;
306}
307
309{
310 /* this is just a wrapper around exit() */
311 ringsel_exit(C, op);
312}
313
315 uint base_index,
316 BMEdge *e,
317 const int previewlines)
318{
319 if (e != lcd->eed) {
320 lcd->eed = e;
321 lcd->ob = lcd->vc.obedit;
322 lcd->base_index = base_index;
323 lcd->em = lcd->vc.em;
324 ringsel_find_edge(lcd, previewlines);
325 }
326 else if (e == nullptr) {
327 lcd->ob = nullptr;
328 lcd->em = nullptr;
329 lcd->base_index = UINT_MAX;
330 }
331}
332
333static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines)
334{
335 struct {
336 Object *ob;
337 BMEdge *eed;
338 float dist;
339 int base_index;
340 } best{};
341 best.dist = ED_view3d_select_dist_px();
342
343 uint base_index;
345 &lcd->vc, &best.dist, nullptr, false, false, nullptr, lcd->bases, &base_index);
346
347 if (eed_test) {
348 best.ob = lcd->bases[base_index]->object;
349 best.eed = eed_test;
350 best.base_index = base_index;
351 }
352
353 if (best.eed) {
355 }
356
357 loopcut_update_edge(lcd, best.base_index, best.eed, previewlines);
358}
359
360/* called by both init() and exec() */
362{
363 /* Check whether both `rv3d` and `event` is present, this way we allow the loopcut operator to
364 * run non-interactively no matter whether the graphical UI is present or not (e.g. from scripts
365 * with UI running, or entirely in the background with `blender -b`). */
367 const bool is_interactive = (rv3d != nullptr) && (event != nullptr);
368
369 /* Use for redo - intentionally wrap int to uint. */
370 struct {
371 uint base_index;
372 uint e_index;
373 } exec_data{};
374 exec_data.base_index = uint(RNA_int_get(op->ptr, "object_index"));
375 exec_data.e_index = uint(RNA_int_get(op->ptr, "edge_index"));
376
377 const Scene *scene = CTX_data_scene(C);
378 ViewLayer *view_layer = CTX_data_view_layer(C);
379
381 scene, view_layer, CTX_wm_view3d(C));
382
383 if (is_interactive) {
384 for (Base *base : bases) {
385 Object *ob_iter = base->object;
388 {
390 op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display");
391 break;
392 }
393 }
394 }
395
396 if (is_interactive) {
398 }
399
400 /* for re-execution, check edge index is in range before we setup ringsel */
401 bool ok = true;
402 if (is_interactive == false) {
403 if (exec_data.base_index >= bases.size()) {
404 ok = false;
405 }
406 else {
407 Object *ob_iter = bases[exec_data.base_index]->object;
409 if (exec_data.e_index >= em->bm->totedge) {
410 ok = false;
411 }
412 }
413 }
414
415 if (!ok || !ringsel_init(C, op, true)) {
416 return OPERATOR_CANCELLED;
417 }
418
419 /* add a modal handler for this operator - handles loop selection */
420 if (is_interactive) {
423 }
424
425 RingSelOpData *lcd = static_cast<RingSelOpData *>(op->customdata);
426
427 lcd->bases = std::move(bases);
428 lcd->geom_cache.reinitialize(lcd->bases.size());
429
430 if (is_interactive) {
431 copy_v2_v2_int(lcd->vc.mval, event->mval);
432 loopcut_mouse_move(lcd, is_interactive ? 1 : 0);
433 }
434 else {
435
436 Object *ob_iter = lcd->bases[exec_data.base_index]->object;
438
439 BMEdge *e;
441 e = BM_edge_at_index(lcd->vc.em->bm, exec_data.e_index);
442 loopcut_update_edge(lcd, exec_data.base_index, e, 0);
443 }
444
445#ifdef USE_LOOPSLIDE_HACK
446 /* for use in macro so we can restore, HACK */
447 {
448 ToolSettings *settings = scene->toolsettings;
449 const bool mesh_select_mode[3] = {
450 (settings->selectmode & SCE_SELECT_VERTEX) != 0,
451 (settings->selectmode & SCE_SELECT_EDGE) != 0,
452 (settings->selectmode & SCE_SELECT_FACE) != 0,
453 };
454
455 RNA_boolean_set_array(op->ptr, "mesh_select_mode_init", mesh_select_mode);
456 }
457#endif
458
459 if (is_interactive) {
460 char buf[UI_MAX_DRAW_STR];
461 char str_rep[NUM_STR_REP_LEN * 2];
462 if (hasNumInput(&lcd->num)) {
463 outputNumInput(&lcd->num, str_rep, scene->unit);
464 }
465 else {
466 BLI_snprintf(str_rep, NUM_STR_REP_LEN, "%d", int(lcd->cuts));
467 BLI_snprintf(str_rep + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%.2f", lcd->smoothness);
468 }
469 SNPRINTF(buf, IFACE_("Cuts: %s, Smoothness: %s"), str_rep, str_rep + NUM_STR_REP_LEN);
471
472 WorkspaceStatus status(C);
473 status.item(IFACE_("Confirm"), ICON_MOUSE_LMB);
474 status.item(IFACE_("Cancel"), ICON_MOUSE_RMB);
475 status.item(IFACE_("Select Ring"), ICON_MOUSE_MOVE);
476 status.item("", ICON_MOUSE_MMB);
477 status.item(IFACE_("Number of Cuts"), ICON_EVENT_PAGEUP, ICON_EVENT_PAGEDOWN);
478 status.item(IFACE_("Smoothness"), ICON_EVENT_ALT, ICON_MOUSE_MMB);
480 }
481
482 ringsel_finish(C, op);
483 ringsel_exit(C, op);
484 return OPERATOR_FINISHED;
485}
486
488{
489 /* When accessed as a tool, get the active edge from the pre-selection gizmo. */
490 {
491 ARegion *region = CTX_wm_region(C);
492 wmGizmoMap *gzmap = region->runtime->gizmo_map;
493 wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap,
494 "VIEW3D_GGT_mesh_preselect_edgering") :
495 nullptr;
496 if ((gzgroup != nullptr) && gzgroup->gizmos.first) {
497 wmGizmo *gz = static_cast<wmGizmo *>(gzgroup->gizmos.first);
498 const int object_index = RNA_int_get(gz->ptr, "object_index");
499 const int edge_index = RNA_int_get(gz->ptr, "edge_index");
500
501 if (object_index != -1 && edge_index != -1) {
502 RNA_int_set(op->ptr, "object_index", object_index);
503 RNA_int_set(op->ptr, "edge_index", edge_index);
504 return loopcut_init(C, op, nullptr);
505 }
506 return OPERATOR_CANCELLED;
507 }
508 }
509
510 return loopcut_init(C, op, event);
511}
512
514{
515 return loopcut_init(C, op, nullptr);
516}
517
519{
520 /* finish */
522 ED_workspace_status_text(C, nullptr);
524
525 if (lcd->eed) {
526 /* set for redo */
528 RNA_int_set(op->ptr, "object_index", lcd->base_index);
529 RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed));
530
531 /* execute */
532 ringsel_finish(C, op);
533 ringsel_exit(C, op);
534 }
535 else {
536 ringcut_cancel(C, op);
537 return OPERATOR_CANCELLED;
538 }
539
540 return OPERATOR_FINISHED;
541}
542
544{
545 if (event->type == NDOF_MOTION) {
547 }
548
549 RingSelOpData *lcd = static_cast<RingSelOpData *>(op->customdata);
550 float cuts = lcd->cuts;
551 float smoothness = lcd->smoothness;
552 bool show_cuts = false;
553 const bool has_numinput = hasNumInput(&lcd->num);
554
555 lcd->vc = em_setup_viewcontext(C);
556 lcd->region = lcd->vc.region;
557
559
560 /* using the keyboard to input the number of cuts */
561 /* Modal numinput active, try to handle numeric inputs first... */
562 if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &lcd->num, event)) {
563 float values[2] = {cuts, smoothness};
564 applyNumInput(&lcd->num, values);
565 cuts = values[0];
566 smoothness = values[1];
567 }
568 else {
569 bool handled = false;
570 switch (event->type) {
571 case EVT_RETKEY:
572 case EVT_PADENTER:
573 case LEFTMOUSE: /* confirm */ /* XXX hardcoded */
574 if (event->val == KM_PRESS) {
575 return loopcut_finish(lcd, C, op);
576 }
577
579 handled = true;
580 break;
581 case RIGHTMOUSE: /* abort */ /* XXX hardcoded */
583 ringsel_exit(C, op);
584 ED_workspace_status_text(C, nullptr);
586
587 return OPERATOR_CANCELLED;
588 case EVT_ESCKEY:
589 if (event->val == KM_RELEASE) {
590 /* cancel */
592 ED_workspace_status_text(C, nullptr);
594
595 ringcut_cancel(C, op);
596 return OPERATOR_CANCELLED;
597 }
598
600 handled = true;
601 break;
602 case MOUSEPAN:
603 if ((event->modifier & KM_ALT) == 0) {
604 cuts += 0.02f * (event->xy[1] - event->prev_xy[1]);
605 if (cuts < 1 && lcd->cuts >= 1) {
606 cuts = 1;
607 }
608 }
609 else {
610 smoothness += 0.002f * (event->xy[1] - event->prev_xy[1]);
611 }
612 handled = true;
613 break;
614 case EVT_PADPLUSKEY:
615 case EVT_PAGEUPKEY:
616 case WHEELUPMOUSE: /* change number of cuts */
617 if (event->val == KM_RELEASE) {
618 break;
619 }
620 if ((event->modifier & KM_ALT) == 0) {
621 cuts += 1;
622 }
623 else {
624 smoothness += 0.05f;
625 }
626 handled = true;
627 break;
628 case EVT_PADMINUS:
629 case EVT_PAGEDOWNKEY:
630 case WHEELDOWNMOUSE: /* change number of cuts */
631 if (event->val == KM_RELEASE) {
632 break;
633 }
634 if ((event->modifier & KM_ALT) == 0) {
635 cuts = max_ff(cuts - 1, 1);
636 }
637 else {
638 smoothness -= 0.05f;
639 }
640 handled = true;
641 break;
642 case MOUSEMOVE: {
643/* mouse moved somewhere to select another loop */
644
645/* This is normally disabled for all modal operators.
646 * This is an exception since mouse movement doesn't relate to numeric input.
647 *
648 * If numeric input changes we'll need to add this back see: D2973 */
649#if 0
650 if (!has_numinput)
651#endif
652 {
653 lcd->vc.mval[0] = event->mval[0];
654 lcd->vc.mval[1] = event->mval[1];
655 loopcut_mouse_move(lcd, int(lcd->cuts));
656
658 handled = true;
659 }
660 break;
661 }
662 default: {
663 break;
664 }
665 }
666
667 /* Modal numinput inactive, try to handle numeric inputs last... */
668 if (!handled && event->val == KM_PRESS && handleNumInput(C, &lcd->num, event)) {
669 float values[2] = {cuts, smoothness};
670 applyNumInput(&lcd->num, values);
671 cuts = values[0];
672 smoothness = values[1];
673 }
674 }
675
676 if (cuts != lcd->cuts) {
677 /* allow zero so you can backspace and type in a value
678 * otherwise 1 as minimum would make more sense */
679 lcd->cuts = clamp_f(cuts, 0, SUBD_CUTS_MAX);
680 RNA_int_set(op->ptr, "number_cuts", int(lcd->cuts));
681 ringsel_find_edge(lcd, int(lcd->cuts));
682 show_cuts = true;
684 }
685
686 if (smoothness != lcd->smoothness) {
688 RNA_float_set(op->ptr, "smoothness", lcd->smoothness);
689 show_cuts = true;
691 }
692
693 if (show_cuts) {
694 Scene *sce = CTX_data_scene(C);
695 char buf[UI_MAX_DRAW_STR];
696 char str_rep[NUM_STR_REP_LEN * 2];
697 if (hasNumInput(&lcd->num)) {
698 outputNumInput(&lcd->num, str_rep, sce->unit);
699 }
700 else {
701 BLI_snprintf(str_rep, NUM_STR_REP_LEN, "%d", int(lcd->cuts));
702 BLI_snprintf(str_rep + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%.2f", smoothness);
703 }
704 SNPRINTF(buf, IFACE_("Cuts: %s, Smoothness: %s"), str_rep, str_rep + NUM_STR_REP_LEN);
706 }
707
708 /* keep going until the user confirms */
710}
711
712/* for bmesh this tool is in bmesh_select.c */
713#if 0
714
716{
717 /* description */
718 ot->name = "Edge Ring Select";
719 ot->idname = "MESH_OT_edgering_select";
720 ot->description = "Select an edge ring";
721
722 /* callbacks */
723 ot->invoke = ringsel_invoke;
725
726 /* flags */
728
729 RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
730}
731
732#endif
733
735{
736 PropertyRNA *prop;
737
738 /* description */
739 ot->name = "Loop Cut";
740 ot->idname = "MESH_OT_loopcut";
741 ot->description = "Add a new loop between existing loops";
742
743 /* callbacks */
744 ot->invoke = ringcut_invoke;
745 ot->exec = loopcut_exec;
746 ot->modal = loopcut_modal;
747 ot->cancel = ringcut_cancel;
748 /* Note the #RegionView3D is needed for interactive use, the operator must check this. */
749 ot->poll = ED_operator_editmesh;
750
751 /* flags */
753
754 /* properties */
755 prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000000, "Number of Cuts", "", 1, 100);
756 /* avoid re-using last var because it can cause
757 * _very_ high poly meshes and annoy users (or worse crash) */
759
760 prop = RNA_def_float(ot->srna,
761 "smoothness",
762 0.0f,
763 -1e3f,
764 1e3f,
765 "Smoothness",
766 "Smoothness factor",
770
772
773 prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE);
776 RNA_def_property_ui_text(prop, "Falloff", "Falloff type of the feather");
778 BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */
779
780 /* For redo only. */
781 prop = RNA_def_int(ot->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", 0, INT_MAX);
784 prop = RNA_def_int(ot->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", 0, INT_MAX);
786
787#ifdef USE_LOOPSLIDE_HACK
788 prop = RNA_def_boolean_array(ot->srna, "mesh_select_mode_init", 3, nullptr, "", "");
790#endif
791}
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
blender::Span< blender::float3 > BKE_editmesh_vert_coords_when_deformed(Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, Object *obedit, blender::Array< blender::float3 > &r_alloc)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
blender::Vector< Base * > BKE_view_layer_array_from_bases_in_edit_mode(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
Object * BKE_modifiers_is_deformed_by_lattice(Object *ob)
Object * BKE_modifiers_is_deformed_by_armature(Object *ob)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
@ B_UNIT_NONE
Definition BKE_unit.hh:123
MINLINE float max_ff(float a, float b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
#define BLT_I18NCONTEXT_ID_CURVE_LEGACY
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_ID_MESH
void DEG_id_tag_update(ID *id, unsigned int flags)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1009
Object is a sort of wrapper for general info.
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
@ SCE_SELECT_EDGE
@ PROP_INVSQUARE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ OP_IS_MODAL_CURSOR_REGION
void EDBM_flag_disable_all(BMEditMesh *em, char hflag)
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params)
void EDBM_preselect_edgering_destroy(EditMesh_PreSelEdgeRing *psel)
void EDBM_preselect_edgering_clear(EditMesh_PreSelEdgeRing *psel)
BMEdge * EDBM_edge_find_nearest_ex(ViewContext *vc, float *dist_px_manhattan, float *r_dist_center, bool use_select_bias, bool use_cycle, BMEdge **r_eed_zbuf, blender::Span< Base * > bases, uint *r_base_index)
ViewContext em_setup_viewcontext(bContext *C)
void EDBM_selectmode_flush(BMEditMesh *em)
void EDBM_preselect_edgering_draw(EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
void EDBM_selectmode_flush_ex(BMEditMesh *em, short selectmode)
bool EDBM_selectmode_disable_multi(bContext *C, short selectmode_disable, short selectmode_fallback)
EditMesh_PreSelEdgeRing * EDBM_preselect_edgering_create()
void EDBM_preselect_edgering_update_from_edge(EditMesh_PreSelEdgeRing *psel, BMesh *bm, BMEdge *eed_start, int previewlines, blender::Span< blender::float3 > vert_positions)
void initNumInput(NumInput *n)
Definition numinput.cc:69
#define NUM_STR_REP_LEN
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition numinput.cc:311
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:189
void outputNumInput(NumInput *n, char *str, const UnitSettings &unit_settings)
Definition numinput.cc:87
@ NUM_NO_NEGATIVE
@ NUM_NO_FRACTION
bool hasNumInput(const NumInput *n)
Definition numinput.cc:170
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:872
bool ED_operator_editmesh_region_view3d(bContext *C)
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1040
bool ED_operator_editmesh(bContext *C)
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:639
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
#define REGION_DRAW_POST_VIEW
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
float ED_view3d_select_dist_px()
void view3d_operator_needs_gpu(const bContext *C)
void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
Read Guarded memory(de)allocation.
@ PROP_ENUM
Definition RNA_types.hh:154
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
@ PROP_NONE
Definition RNA_types.hh:221
#define C
Definition RandGen.cpp:29
#define UI_MAX_DRAW_STR
#define NC_GEOM
Definition WM_types.hh:390
@ KM_ALT
Definition WM_types.hh:277
@ OPTYPE_BLOCKING
Definition WM_types.hh:184
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_SELECT
Definition WM_types.hh:505
@ KM_PRESS
Definition WM_types.hh:308
@ KM_RELEASE
Definition WM_types.hh:309
@ BM_ELEM_SELECT
#define BM_elem_index_get(ele)
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)
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
#define BM_EDGE
@ SUBDIV_SELECT_INNER
@ SUBDIV_SELECT_LOOPCUT
@ SUBDIV_SELECT_NONE
void BM_mesh_esubdivide(BMesh *bm, char edge_hflag, float smooth, short smooth_falloff, bool use_smooth_even, float fractal, float along_normal, int numcuts, int seltype, int cornertype, short use_single_edge, short use_grid_fill, short use_only_quads, int seed)
@ SUBD_CORNER_PATH
bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len)
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
void * BMW_begin(BMWalker *walker, void *start)
void BMW_init(BMWalker *walker, BMesh *bm, int type, short mask_vert, short mask_edge, short mask_face, BMWFlag flag, int layer)
Initialize Walker.
void BMW_end(BMWalker *walker)
End Walker.
void * BMW_step(BMWalker *walker)
Step Walker.
@ BMW_EDGERING
#define BMW_NIL_LAY
@ BMW_FLAG_TEST_HIDDEN
#define BMW_MASK_NOP
void item(std::string text, int icon1, int icon2=0)
Definition area.cc:979
int64_t size() const
static void loopcut_update_edge(RingSelOpData *lcd, uint base_index, BMEdge *e, const int previewlines)
static void ringsel_draw(const bContext *, ARegion *, void *arg)
static void ringsel_exit(bContext *, wmOperator *op)
static wmOperatorStatus loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
static void ringsel_find_edge(RingSelOpData *lcd, const int previewlines)
static wmOperatorStatus loopcut_exec(bContext *C, wmOperator *op)
#define SUBD_SMOOTH_MAX
static wmOperatorStatus loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
static void ringcut_cancel(bContext *C, wmOperator *op)
static wmOperatorStatus ringcut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
#define SUBD_CUTS_MAX
void MESH_OT_loopcut(wmOperatorType *ot)
static void ringsel_finish(bContext *C, wmOperator *op)
static void edgering_select(RingSelOpData *lcd)
static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines)
void MESH_OT_edgering_select(wmOperatorType *ot)
#define UINT_MAX
Definition hash_md5.cc:44
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
VecBase< float, 3 > float3
void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const bool *values)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_boolean_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const bool *default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_enum_default(PropertyRNA *prop, int value)
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item)
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_proportional_falloff_curve_only_items[]
Definition rna_scene.cc:112
ARegionRuntimeHandle * runtime
BMVert * v1
BMVert * v2
short selectmode
int totedge
struct Object * object
Definition DNA_ID.h:404
void * first
Array< float3 > allocated_vert_positions
Span< float3 > vert_positions
short idx_max
short val_flag[NUM_MAX_ELEMENTS]
int unit_type[NUM_MAX_ELEMENTS]
Depsgraph * depsgraph
BMEditMesh * em
Vector< Base * > bases
Array< MeshCoordsCache > geom_cache
EditMesh_PreSelEdgeRing * presel_edgering
struct ToolSettings * toolsettings
struct UnitSettings unit
ARegion * region
Definition ED_view3d.hh:77
int mval[2]
Definition ED_view3d.hh:82
Scene * scene
Definition ED_view3d.hh:73
BMEditMesh * em
Definition ED_view3d.hh:81
Object * obedit
Definition ED_view3d.hh:76
Depsgraph * depsgraph
Definition ED_view3d.hh:72
wmEventModifierFlag modifier
Definition WM_types.hh:771
wmEventType type
Definition WM_types.hh:754
short val
Definition WM_types.hh:756
int mval[2]
Definition WM_types.hh:760
PointerRNA * ptr
struct ReportList * reports
struct PointerRNA * ptr
struct wmOperator * opm
void WM_main_add_notifier(uint type, void *reference)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ MOUSEPAN
@ RIGHTMOUSE
@ WHEELUPMOUSE
@ EVT_PAGEUPKEY
@ EVT_PAGEDOWNKEY
@ EVT_PADENTER
@ WHEELDOWNMOUSE
@ MOUSEMOVE
@ EVT_PADMINUS
@ LEFTMOUSE
@ NDOF_MOTION
@ EVT_ESCKEY
@ EVT_PADPLUSKEY
@ EVT_RETKEY
wmOperatorType * ot
Definition wm_files.cc:4225
wmGizmoGroup * WM_gizmomap_group_find(wmGizmoMap *gzmap, const char *idname)
void WM_operatortype_props_advanced_begin(wmOperatorType *ot)