Blender  V2.93
editmesh_loopcut.c
Go to the documentation of this file.
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  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "DNA_object_types.h"
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "BLI_math.h"
29 #include "BLI_string.h"
30 
31 #include "BLT_translation.h"
32 
33 #include "DNA_mesh_types.h"
34 
35 #include "BKE_context.h"
36 #include "BKE_editmesh.h"
37 #include "BKE_layer.h"
38 #include "BKE_modifier.h"
39 #include "BKE_report.h"
40 #include "BKE_unit.h"
41 
42 #include "UI_interface.h"
43 
44 #include "ED_mesh.h"
45 #include "ED_numinput.h"
46 #include "ED_screen.h"
47 #include "ED_space_api.h"
48 #include "ED_view3d.h"
49 
50 #include "RNA_access.h"
51 #include "RNA_define.h"
52 #include "RNA_enum_types.h"
53 
54 #include "WM_api.h"
55 #include "WM_types.h"
56 
57 #include "DEG_depsgraph.h"
58 #include "DEG_depsgraph_query.h"
59 
60 #include "mesh_intern.h" /* own include */
61 
62 #define SUBD_SMOOTH_MAX 4.0f
63 #define SUBD_CUTS_MAX 500
64 
65 /* ringsel operator */
66 
69  const float (*coords)[3];
70 };
71 
72 /* struct for properties used while drawing */
73 typedef struct RingSelOpData {
74  ARegion *region; /* region that ringsel was activated in */
75  void *draw_handle; /* for drawing preview loop */
76 
78 
80 
82 
85 
87 
88  /* These values switch objects based on the object under the cursor. */
93 
95 
96  bool extend;
97  bool do_cut;
98 
99  float cuts; /* cuts as float so smooth mouse pan works in small increments */
100  float smoothness;
102 
103 /* modal loop selection drawing callback */
104 static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
105 {
106  RingSelOpData *lcd = arg;
108 }
109 
111 {
112  if (!lcd->eed) {
113  return;
114  }
115 
116  if (!lcd->extend) {
117  for (uint base_index = 0; base_index < lcd->bases_len; base_index++) {
118  Object *ob_iter = lcd->bases[base_index]->object;
119  BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
123  }
124  }
125 
126  BMEditMesh *em = lcd->em;
127  BMEdge *eed_start = lcd->eed;
128  BMWalker walker;
129  BMEdge *eed;
130  BMW_init(&walker,
131  em->bm,
132  BMW_EDGERING,
133  BMW_MASK_NOP,
134  BMW_MASK_NOP,
135  BMW_MASK_NOP,
137  BMW_NIL_LAY);
138 
139  for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
140  BM_edge_select_set(em->bm, eed, true);
141  }
142  BMW_end(&walker);
143 }
144 
145 static void ringsel_find_edge(RingSelOpData *lcd, const int previewlines)
146 {
147  if (lcd->eed) {
148  struct MeshCoordsCache *gcache = &lcd->geom_cache[lcd->base_index];
149  if (gcache->is_init == false) {
150  Scene *scene_eval = (Scene *)DEG_get_evaluated_id(lcd->vc.depsgraph, &lcd->vc.scene->id);
151  Object *ob_eval = DEG_get_evaluated_object(lcd->vc.depsgraph, lcd->ob);
152  BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval);
154  lcd->vc.depsgraph, em_eval, scene_eval, ob_eval, NULL, &gcache->is_alloc);
155  gcache->is_init = true;
156  }
157 
159  lcd->presel_edgering, lcd->em->bm, lcd->eed, previewlines, gcache->coords);
160  }
161  else {
163  }
164 }
165 
167 {
168  RingSelOpData *lcd = op->customdata;
169  const int cuts = RNA_int_get(op->ptr, "number_cuts");
170  const float smoothness = RNA_float_get(op->ptr, "smoothness");
171  const int smooth_falloff = RNA_enum_get(op->ptr, "falloff");
172 #ifdef BMW_EDGERING_NGON
173  const bool use_only_quads = false;
174 #else
175  const bool use_only_quads = false;
176 #endif
177 
178  if (lcd->eed) {
179  BMEditMesh *em = lcd->em;
180  BMVert *v_eed_orig[2] = {lcd->eed->v1, lcd->eed->v2};
181 
182  edgering_select(lcd);
183 
184  if (lcd->do_cut) {
185  const bool is_macro = (op->opm != NULL);
186  /* a single edge (rare, but better support) */
187  const bool is_edge_wire = BM_edge_is_wire(lcd->eed);
188  const bool is_single = is_edge_wire || !BM_edge_is_any_face_len_test(lcd->eed, 4);
189  const int seltype = is_edge_wire ? SUBDIV_SELECT_INNER :
191 
192  /* Enable grid-fill, so that intersecting loop-cut works as one would expect.
193  * Note though that it will break edge-slide in this specific case.
194  * See T31939. */
197  smoothness,
198  smooth_falloff,
199  true,
200  0.0f,
201  0.0f,
202  cuts,
203  seltype,
205  0,
206  true,
207  use_only_quads,
208  0);
209 
210  /* when used in a macro the tessfaces will be recalculated anyway,
211  * this is needed here because modifiers depend on updated tessellation, see T45920 */
212  EDBM_update_generic(lcd->ob->data, true, true);
213 
214  if (is_single) {
215  /* de-select endpoints */
216  BM_vert_select_set(em->bm, v_eed_orig[0], false);
217  BM_vert_select_set(em->bm, v_eed_orig[1], false);
218 
220  }
221  /* we cant slide multiple edges in vertex select mode */
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. */
227  /* pass, the change will flush selection */
228  }
229  else {
230  /* else flush explicitly */
232  }
233  }
234  else {
235  /* XXX Is this piece of code ever used now? Simple loop select is now
236  * in editmesh_select.c (around line 1000)... */
237  /* sets as active, useful for other tools */
238  if (em->selectmode & SCE_SELECT_VERTEX) {
239  /* low priority TODO, get vertrex close to mouse */
240  BM_select_history_store(em->bm, lcd->eed->v1);
241  }
242  if (em->selectmode & SCE_SELECT_EDGE) {
243  BM_select_history_store(em->bm, lcd->eed);
244  }
245 
249  }
250  }
251 }
252 
253 /* called when modal loop selection is done... */
255 {
256  RingSelOpData *lcd = op->customdata;
257 
258  /* deactivate the extra drawing stuff in 3D-View */
260 
262 
263  for (uint i = 0; i < lcd->bases_len; i++) {
264  struct MeshCoordsCache *gcache = &lcd->geom_cache[i];
265  if (gcache->is_alloc) {
266  MEM_freeN((void *)gcache->coords);
267  }
268  }
269  MEM_freeN(lcd->geom_cache);
270 
271  MEM_freeN(lcd->bases);
272 
274 
275  /* free the custom data */
276  MEM_freeN(lcd);
277  op->customdata = NULL;
278 }
279 
280 /* called when modal loop selection gets set up... */
281 static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
282 {
283  RingSelOpData *lcd;
285 
286  /* alloc new customdata */
287  lcd = op->customdata = MEM_callocN(sizeof(RingSelOpData), "ringsel Modal Op Data");
288 
289  em_setup_viewcontext(C, &lcd->vc);
290 
292 
293  /* assign the drawing handle for drawing preview line... */
294  lcd->region = CTX_wm_region(C);
298  /* Initialize once the cursor is over a mesh. */
299  lcd->ob = NULL;
300  lcd->em = NULL;
301  lcd->extend = do_cut ? false : RNA_boolean_get(op->ptr, "extend");
302  lcd->do_cut = do_cut;
303  lcd->cuts = RNA_int_get(op->ptr, "number_cuts");
304  lcd->smoothness = RNA_float_get(op->ptr, "smoothness");
305 
306  initNumInput(&lcd->num);
307  lcd->num.idx_max = 1;
309  /* No specific flags for smoothness. */
310  lcd->num.unit_sys = scene->unit.system;
311  lcd->num.unit_type[0] = B_UNIT_NONE;
312  lcd->num.unit_type[1] = B_UNIT_NONE;
313 
315 
316  return 1;
317 }
318 
320 {
321  /* this is just a wrapper around exit() */
322  ringsel_exit(C, op);
323 }
324 
326  uint base_index,
327  BMEdge *e,
328  const int previewlines)
329 {
330  if (e != lcd->eed) {
331  lcd->eed = e;
332  lcd->ob = lcd->vc.obedit;
333  lcd->base_index = base_index;
334  lcd->em = lcd->vc.em;
335  ringsel_find_edge(lcd, previewlines);
336  }
337  else if (e == NULL) {
338  lcd->ob = NULL;
339  lcd->em = NULL;
340  lcd->base_index = UINT_MAX;
341  }
342 }
343 
344 static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines)
345 {
346  struct {
347  Object *ob;
348  BMEdge *eed;
349  float dist;
350  int base_index;
351  } best = {
352  .dist = ED_view3d_select_dist_px(),
353  };
354 
355  uint base_index;
356  BMEdge *eed_test = EDBM_edge_find_nearest_ex(
357  &lcd->vc, &best.dist, NULL, false, false, NULL, lcd->bases, lcd->bases_len, &base_index);
358 
359  if (eed_test) {
360  best.ob = lcd->bases[base_index]->object;
361  best.eed = eed_test;
362  best.base_index = base_index;
363  }
364 
365  if (best.eed) {
366  ED_view3d_viewcontext_init_object(&lcd->vc, best.ob);
367  }
368 
369  loopcut_update_edge(lcd, best.base_index, best.eed, previewlines);
370 }
371 
372 /* called by both init() and exec() */
373 static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
374 {
375  const bool is_interactive = (event != NULL);
376 
377  /* Use for redo - intentionally wrap int to uint. */
378  const struct {
379  uint base_index;
380  uint e_index;
381  } exec_data = {
382  .base_index = (uint)RNA_int_get(op->ptr, "object_index"),
383  .e_index = (uint)RNA_int_get(op->ptr, "edge_index"),
384  };
385 
386  ViewLayer *view_layer = CTX_data_view_layer(C);
387 
388  uint bases_len;
390  view_layer, CTX_wm_view3d(C), &bases_len);
391 
392  if (is_interactive) {
393  for (uint base_index = 0; base_index < bases_len; base_index++) {
394  Object *ob_iter = bases[base_index]->object;
397  BKE_report(
398  op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display");
399  break;
400  }
401  }
402  }
403 
405 
406  /* for re-execution, check edge index is in range before we setup ringsel */
407  bool ok = true;
408  if (is_interactive == false) {
409  if (exec_data.base_index >= bases_len) {
410  ok = false;
411  }
412  else {
413  Object *ob_iter = bases[exec_data.base_index]->object;
414  BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
415  if (exec_data.e_index >= em->bm->totedge) {
416  ok = false;
417  }
418  }
419  }
420 
421  if (!ok || !ringsel_init(C, op, true)) {
422  MEM_freeN(bases);
423  return OPERATOR_CANCELLED;
424  }
425 
426  /* add a modal handler for this operator - handles loop selection */
427  if (is_interactive) {
430  }
431 
432  RingSelOpData *lcd = op->customdata;
433 
434  lcd->bases = bases;
435  lcd->bases_len = bases_len;
436  lcd->geom_cache = MEM_callocN(sizeof(*lcd->geom_cache) * bases_len, __func__);
437 
438  if (is_interactive) {
439  copy_v2_v2_int(lcd->vc.mval, event->mval);
440  loopcut_mouse_move(lcd, is_interactive ? 1 : 0);
441  }
442  else {
443 
444  Object *ob_iter = bases[exec_data.base_index]->object;
445  ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
446 
447  BMEdge *e;
449  e = BM_edge_at_index(lcd->vc.em->bm, exec_data.e_index);
450  loopcut_update_edge(lcd, exec_data.base_index, e, 0);
451  }
452 
453 #ifdef USE_LOOPSLIDE_HACK
454  /* for use in macro so we can restore, HACK */
455  {
457  ToolSettings *settings = scene->toolsettings;
458  const bool mesh_select_mode[3] = {
459  (settings->selectmode & SCE_SELECT_VERTEX) != 0,
460  (settings->selectmode & SCE_SELECT_EDGE) != 0,
461  (settings->selectmode & SCE_SELECT_FACE) != 0,
462  };
463 
464  RNA_boolean_set_array(op->ptr, "mesh_select_mode_init", mesh_select_mode);
465  }
466 #endif
467 
468  if (is_interactive) {
470  C,
471  TIP_("Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts, "
472  "hold Alt for smooth"));
473  return OPERATOR_RUNNING_MODAL;
474  }
475 
476  ringsel_finish(C, op);
477  ringsel_exit(C, op);
478  return OPERATOR_FINISHED;
479 }
480 
481 static int ringcut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
482 {
483  /* When accessed as a tool, get the active edge from the preselection gizmo. */
484  {
485  ARegion *region = CTX_wm_region(C);
486  wmGizmoMap *gzmap = region->gizmo_map;
487  wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap,
488  "VIEW3D_GGT_mesh_preselect_edgering") :
489  NULL;
490  if ((gzgroup != NULL) && gzgroup->gizmos.first) {
491  wmGizmo *gz = gzgroup->gizmos.first;
492  const int object_index = RNA_int_get(gz->ptr, "object_index");
493  const int edge_index = RNA_int_get(gz->ptr, "edge_index");
494 
495  if (object_index != -1 && edge_index != -1) {
496  RNA_int_set(op->ptr, "object_index", object_index);
497  RNA_int_set(op->ptr, "edge_index", edge_index);
498  return loopcut_init(C, op, NULL);
499  }
500  return OPERATOR_CANCELLED;
501  }
502  }
503 
504  return loopcut_init(C, op, event);
505 }
506 
508 {
509  return loopcut_init(C, op, NULL);
510 }
511 
513 {
514  /* finish */
517 
518  if (lcd->eed) {
519  /* set for redo */
521  RNA_int_set(op->ptr, "object_index", lcd->base_index);
522  RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed));
523 
524  /* execute */
525  ringsel_finish(C, op);
526  ringsel_exit(C, op);
527  }
528  else {
529  ringcut_cancel(C, op);
530  return OPERATOR_CANCELLED;
531  }
532 
533  return OPERATOR_FINISHED;
534 }
535 
536 static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
537 {
538  if (event->type == NDOF_MOTION) {
539  return OPERATOR_PASS_THROUGH;
540  }
541 
542  RingSelOpData *lcd = op->customdata;
543  float cuts = lcd->cuts;
544  float smoothness = lcd->smoothness;
545  bool show_cuts = false;
546  const bool has_numinput = hasNumInput(&lcd->num);
547 
548  em_setup_viewcontext(C, &lcd->vc);
549  lcd->region = lcd->vc.region;
550 
552 
553  /* using the keyboard to input the number of cuts */
554  /* Modal numinput active, try to handle numeric inputs first... */
555  if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &lcd->num, event)) {
556  float values[2] = {cuts, smoothness};
557  applyNumInput(&lcd->num, values);
558  cuts = values[0];
559  smoothness = values[1];
560  }
561  else {
562  bool handled = false;
563  switch (event->type) {
564  case EVT_RETKEY:
565  case EVT_PADENTER:
566  case LEFTMOUSE: /* confirm */ /* XXX hardcoded */
567  if (event->val == KM_PRESS) {
568  return loopcut_finish(lcd, C, op);
569  }
570 
572  handled = true;
573  break;
574  case RIGHTMOUSE: /* abort */ /* XXX hardcoded */
576  ringsel_exit(C, op);
578 
579  return OPERATOR_CANCELLED;
580  case EVT_ESCKEY:
581  if (event->val == KM_RELEASE) {
582  /* cancel */
585 
586  ringcut_cancel(C, op);
587  return OPERATOR_CANCELLED;
588  }
589 
591  handled = true;
592  break;
593  case MOUSEPAN:
594  if (event->alt == 0) {
595  cuts += 0.02f * (event->y - event->prevy);
596  if (cuts < 1 && lcd->cuts >= 1) {
597  cuts = 1;
598  }
599  }
600  else {
601  smoothness += 0.002f * (event->y - event->prevy);
602  }
603  handled = true;
604  break;
605  case EVT_PADPLUSKEY:
606  case EVT_PAGEUPKEY:
607  case WHEELUPMOUSE: /* change number of cuts */
608  if (event->val == KM_RELEASE) {
609  break;
610  }
611  if (event->alt == 0) {
612  cuts += 1;
613  }
614  else {
615  smoothness += 0.05f;
616  }
617  handled = true;
618  break;
619  case EVT_PADMINUS:
620  case EVT_PAGEDOWNKEY:
621  case WHEELDOWNMOUSE: /* change number of cuts */
622  if (event->val == KM_RELEASE) {
623  break;
624  }
625  if (event->alt == 0) {
626  cuts = max_ff(cuts - 1, 1);
627  }
628  else {
629  smoothness -= 0.05f;
630  }
631  handled = true;
632  break;
633  case MOUSEMOVE: {
634  /* mouse moved somewhere to select another loop */
635 
636  /* This is normally disabled for all modal operators.
637  * This is an exception since mouse movement doesn't relate to numeric input.
638  *
639  * If numeric input changes we'll need to add this back see: D2973 */
640 #if 0
641  if (!has_numinput)
642 #endif
643  {
644  lcd->vc.mval[0] = event->mval[0];
645  lcd->vc.mval[1] = event->mval[1];
646  loopcut_mouse_move(lcd, (int)lcd->cuts);
647 
649  handled = true;
650  }
651  break;
652  }
653  }
654 
655  /* Modal numinput inactive, try to handle numeric inputs last... */
656  if (!handled && event->val == KM_PRESS && handleNumInput(C, &lcd->num, event)) {
657  float values[2] = {cuts, smoothness};
658  applyNumInput(&lcd->num, values);
659  cuts = values[0];
660  smoothness = values[1];
661  }
662  }
663 
664  if (cuts != lcd->cuts) {
665  /* allow zero so you can backspace and type in a value
666  * otherwise 1 as minimum would make more sense */
667  lcd->cuts = clamp_f(cuts, 0, SUBD_CUTS_MAX);
668  RNA_int_set(op->ptr, "number_cuts", (int)lcd->cuts);
669  ringsel_find_edge(lcd, (int)lcd->cuts);
670  show_cuts = true;
672  }
673 
674  if (smoothness != lcd->smoothness) {
675  lcd->smoothness = clamp_f(smoothness, -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
676  RNA_float_set(op->ptr, "smoothness", lcd->smoothness);
677  show_cuts = true;
679  }
680 
681  if (show_cuts) {
682  Scene *sce = CTX_data_scene(C);
683  char buf[UI_MAX_DRAW_STR];
684  char str_rep[NUM_STR_REP_LEN * 2];
685  if (hasNumInput(&lcd->num)) {
686  outputNumInput(&lcd->num, str_rep, &sce->unit);
687  }
688  else {
689  BLI_snprintf(str_rep, NUM_STR_REP_LEN, "%d", (int)lcd->cuts);
690  BLI_snprintf(str_rep + NUM_STR_REP_LEN, NUM_STR_REP_LEN, "%.2f", smoothness);
691  }
692  BLI_snprintf(buf,
693  sizeof(buf),
694  TIP_("Number of Cuts: %s, Smooth: %s (Alt)"),
695  str_rep,
696  str_rep + NUM_STR_REP_LEN);
698  }
699 
700  /* keep going until the user confirms */
701  return OPERATOR_RUNNING_MODAL;
702 }
703 
704 /* for bmesh this tool is in bmesh_select.c */
705 #if 0
706 
708 {
709  /* description */
710  ot->name = "Edge Ring Select";
711  ot->idname = "MESH_OT_edgering_select";
712  ot->description = "Select an edge ring";
713 
714  /* callbacks */
715  ot->invoke = ringsel_invoke;
717 
718  /* flags */
720 
721  RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection");
722 }
723 
724 #endif
725 
727 {
728  PropertyRNA *prop;
729 
730  /* description */
731  ot->name = "Loop Cut";
732  ot->idname = "MESH_OT_loopcut";
733  ot->description = "Add a new loop between existing loops";
734 
735  /* callbacks */
737  ot->exec = loopcut_exec;
741 
742  /* flags */
744 
745  /* properties */
746  prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000000, "Number of Cuts", "", 1, 100);
747  /* avoid re-using last var because it can cause
748  * _very_ high poly meshes and annoy users (or worse crash) */
750 
751  prop = RNA_def_float(ot->srna,
752  "smoothness",
753  0.0f,
754  -1e3f,
755  1e3f,
756  "Smoothness",
757  "Smoothness factor",
761 
763 
764  prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE);
767  RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather");
768  RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
769 
770  /* For redo only. */
771  prop = RNA_def_int(ot->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", 0, INT_MAX);
773  prop = RNA_def_int(ot->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", 0, INT_MAX);
775 
776 #ifdef USE_LOOPSLIDE_HACK
777  prop = RNA_def_boolean_array(ot->srna, "mesh_select_mode_init", 3, NULL, "", "");
779 #endif
780 }
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
const float(* BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph, struct BMEditMesh *em, struct Scene *scene, struct Object *obedit, int *r_vert_len, bool *r_is_alloc))[3]
Definition: editmesh.c:231
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:85
#define BKE_view_layer_array_from_bases_in_edit_mode(view_layer, v3d, r_len)
Definition: BKE_layer.h:423
struct Object * BKE_modifiers_is_deformed_by_armature(struct Object *ob)
struct Object * BKE_modifiers_is_deformed_by_lattice(struct Object *ob)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
@ B_UNIT_NONE
Definition: BKE_unit.h:78
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])
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
#define BLT_I18NCONTEXT_ID_CURVE
#define TIP_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
struct ID * DEG_get_evaluated_id(const struct Depsgraph *depsgraph, struct ID *id)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
Object is a sort of wrapper for general info.
#define SCE_SELECT_FACE
#define SCE_SELECT_VERTEX
#define PROP_INVSQUARE
#define SCE_SELECT_EDGE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ OP_IS_MODAL_CURSOR_REGION
void EDBM_selectmode_flush_ex(struct BMEditMesh *em, const short selectmode)
void EDBM_preselect_edgering_destroy(struct EditMesh_PreSelEdgeRing *psel)
void EDBM_preselect_edgering_clear(struct EditMesh_PreSelEdgeRing *psel)
void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc)
bool EDBM_selectmode_disable(struct Scene *scene, struct BMEditMesh *em, const short selectmode_disable, const short selectmode_fallback)
struct EditMesh_PreSelEdgeRing * EDBM_preselect_edgering_create(void)
void EDBM_update_generic(struct Mesh *me, const bool do_tessellation, const bool is_destructive)
struct BMEdge * EDBM_edge_find_nearest_ex(struct ViewContext *vc, float *dist_px_manhattan, float *r_dist_center, const bool use_select_bias, bool use_cycle, struct BMEdge **r_eed_zbuf, struct Base **bases, uint bases_len, uint *r_base_index)
void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const float matrix[4][4])
void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag)
void EDBM_preselect_edgering_update_from_edge(struct EditMesh_PreSelEdgeRing *psel, struct BMesh *bm, struct BMEdge *eed_start, int previewlines, const float(*coords)[3])
void EDBM_selectmode_flush(struct BMEditMesh *em)
void outputNumInput(NumInput *n, char *str, struct UnitSettings *unit_settings)
Definition: numinput.c:102
void initNumInput(NumInput *n)
Definition: numinput.c:83
#define NUM_STR_REP_LEN
Definition: ED_numinput.h:27
@ NUM_NO_NEGATIVE
Definition: ED_numinput.h:70
@ NUM_NO_FRACTION
Definition: ED_numinput.h:72
bool applyNumInput(NumInput *n, float *vec)
Definition: numinput.c:207
bool hasNumInput(const NumInput *n)
Definition: numinput.c:185
bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event)
bool ED_operator_editmesh_region_view3d(struct bContext *C)
Definition: screen_ops.c:418
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:667
void ED_workspace_status_text(struct bContext *C, const char *str)
Definition: area.c:840
#define REGION_DRAW_POST_VIEW
Definition: ED_space_api.h:66
void * ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *customdata, int type)
Definition: spacetypes.c:238
void ED_region_draw_cb_exit(struct ARegionType *, void *)
Definition: spacetypes.c:253
void ED_view3d_viewcontext_init_object(struct ViewContext *vc, struct Object *obact)
void view3d_operator_needs_opengl(const struct bContext *C)
float ED_view3d_select_dist_px(void)
Read Guarded memory(de)allocation.
@ PROP_ENUM
Definition: RNA_types.h:77
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
@ PROP_NONE
Definition: RNA_types.h:113
#define C
Definition: RandGen.cpp:39
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:90
#define NC_GEOM
Definition: WM_types.h:294
@ OPTYPE_BLOCKING
Definition: WM_types.h:157
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define KM_PRESS
Definition: WM_types.h:242
#define ND_SELECT
Definition: WM_types.h:407
#define KM_RELEASE
Definition: WM_types.h:243
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
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)
Definition: bmesh_mesh.c:2276
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2152
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:104
void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, const float smooth, const short smooth_falloff, const bool use_smooth_even, const float fractal, const float along_normal, const int numcuts, const int seltype, const int cornertype, const short use_single_edge, const short use_grid_fill, const short use_only_quads, const int seed)
@ SUBD_CORNER_PATH
@ SUBDIV_SELECT_INNER
@ SUBDIV_SELECT_LOOPCUT
@ SUBDIV_SELECT_NONE
bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len)
Definition: bmesh_query.c:2514
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_init(BMWalker *walker, BMesh *bm, int type, short mask_vert, short mask_edge, short mask_face, BMWFlag flag, int layer)
Init Walker.
Definition: bmesh_walkers.c:70
void BMW_end(BMWalker *walker)
End Walker.
void * BMW_begin(BMWalker *walker, void *start)
Definition: bmesh_walkers.c:55
void * BMW_step(BMWalker *walker)
Step Walker.
#define BMW_NIL_LAY
@ BMW_FLAG_TEST_HIDDEN
Definition: bmesh_walkers.h:34
#define BMW_MASK_NOP
Definition: bmesh_walkers.h:68
@ BMW_EDGERING
Scene scene
static void loopcut_update_edge(RingSelOpData *lcd, uint base_index, BMEdge *e, const int previewlines)
static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
static void ringsel_find_edge(RingSelOpData *lcd, const int previewlines)
struct RingSelOpData RingSelOpData
#define SUBD_SMOOTH_MAX
static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
static void ringcut_cancel(bContext *C, wmOperator *op)
#define SUBD_CUTS_MAX
static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
static void ringsel_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
static int loopcut_exec(bContext *C, wmOperator *op)
static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
void MESH_OT_loopcut(wmOperatorType *ot)
static void ringsel_finish(bContext *C, wmOperator *op)
static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
static void edgering_select(RingSelOpData *lcd)
static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines)
static int ringcut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void MESH_OT_edgering_select(wmOperatorType *ot)
#define UINT_MAX
Definition: hash_md5.c:58
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const bool *values)
Definition: rna_access.c:6296
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6319
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:6366
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3825
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_enum_default(PropertyRNA *prop, int value)
Definition: rna_define.c:2127
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
Definition: rna_define.c:1676
void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item)
Definition: rna_define.c:1892
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
Definition: rna_define.c:1279
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
Definition: rna_define.c:2870
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3585
PropertyRNA * RNA_def_boolean_array(StructOrFunctionRNA *cont_, const char *identifier, int len, bool *default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3497
const EnumPropertyItem rna_enum_proportional_falloff_curve_only_items[]
Definition: rna_scene.c:132
struct wmGizmoMap * gizmo_map
struct ARegionType * type
BMVert * v1
Definition: bmesh_class.h:134
BMVert * v2
Definition: bmesh_class.h:134
short selectmode
Definition: BKE_editmesh.h:72
struct BMesh * bm
Definition: BKE_editmesh.h:52
int totedge
Definition: bmesh_class.h:297
struct Object * object
void * first
Definition: DNA_listBase.h:47
const float(* coords)[3]
short idx_max
Definition: ED_numinput.h:34
short val_flag[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:43
int unit_sys
Definition: ED_numinput.h:35
int unit_type[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:37
float obmat[4][4]
void * data
struct EditMesh_PreSelEdgeRing * presel_edgering
Depsgraph * depsgraph
ARegion * region
BMEditMesh * em
ViewContext vc
struct MeshCoordsCache * geom_cache
struct ToolSettings * toolsettings
struct UnitSettings unit
struct Depsgraph * depsgraph
Definition: ED_view3d.h:75
int mval[2]
Definition: ED_view3d.h:85
struct Scene * scene
Definition: ED_view3d.h:76
struct ARegion * region
Definition: ED_view3d.h:80
struct BMEditMesh * em
Definition: ED_view3d.h:84
struct Object * obedit
Definition: ED_view3d.h:79
short val
Definition: WM_types.h:579
int mval[2]
Definition: WM_types.h:583
short alt
Definition: WM_types.h:618
short type
Definition: WM_types.h:577
ListBase gizmos
struct PointerRNA * ptr
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct ReportList * reports
struct PointerRNA * ptr
struct wmOperator * opm
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_main_add_notifier(unsigned int type, void *reference)
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.c:3156
wmGizmoGroup * WM_gizmomap_group_find(struct wmGizmoMap *gzmap, const char *idname)
Definition: wm_gizmo_map.c:219
void WM_operatortype_props_advanced_begin(wmOperatorType *ot)