Blender V4.5
editmesh_bevel.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
8
9#include <fmt/format.h>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_object_types.h"
14
15#include "BLI_math_matrix.h"
16#include "BLI_math_vector.h"
17#include "BLI_string.h"
18
19#include "BLT_translation.hh"
20
21#include "BKE_context.hh"
22#include "BKE_editmesh.hh"
23#include "BKE_global.hh"
24#include "BKE_layer.hh"
25#include "BKE_screen.hh"
26#include "BKE_unit.hh"
27
28#include "RNA_access.hh"
29#include "RNA_define.hh"
30#include "RNA_prototypes.hh"
31
32#include "WM_api.hh"
33#include "WM_types.hh"
34
35#include "UI_interface.hh"
36#include "UI_resources.hh"
37
38#include "ED_mesh.hh"
39#include "ED_numinput.hh"
40#include "ED_screen.hh"
41#include "ED_space_api.hh"
42#include "ED_transform.hh"
43#include "ED_util.hh"
44#include "ED_view3d.hh"
45
46#include "mesh_intern.hh" /* own include */
47
48using blender::Vector;
49
50#define MVAL_PIXEL_MARGIN 5.0f
51
52#define PROFILE_HARD_MIN 0.0f
53
54#define SEGMENTS_HARD_MAX 1000
55
56/* which value is mouse movement and numeric input controlling? */
57#define OFFSET_VALUE 0
58#define OFFSET_VALUE_PERCENT 1
59#define PROFILE_VALUE 2
60#define SEGMENTS_VALUE 3
61#define NUM_VALUE_KINDS 4
62
63static const char *value_rna_name[NUM_VALUE_KINDS] = {
64 "offset", "offset_pct", "profile", "segments"};
65static const float value_clamp_min[NUM_VALUE_KINDS] = {0.0f, 0.0f, PROFILE_HARD_MIN, 1.0f};
66static const float value_clamp_max[NUM_VALUE_KINDS] = {1e6, 100.0f, 1.0f, SEGMENTS_HARD_MAX};
67static const float value_start[NUM_VALUE_KINDS] = {0.0f, 0.0f, 0.5f, 1.0f};
68static const float value_scale_per_inch[NUM_VALUE_KINDS] = {0.0f, 100.0f, 1.0f, 4.0f};
69
75
76struct BevelData {
84
86
87 /* modal only */
89 float mcenter[2];
91 short value_mode; /* Which value does mouse movement and numeric input affect? */
92 float segments; /* Segments as float so smooth mouse pan works in small increments */
93
95};
96
97enum {
115};
116
118{
119 if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
120 return RNA_float_get(op->ptr, "offset_pct");
121 }
122 return RNA_float_get(op->ptr, "offset");
123}
124
126{
127 Scene *sce = CTX_data_scene(C);
128 BevelData *opdata = static_cast<BevelData *>(op->customdata);
129
130 char offset_str[NUM_STR_REP_LEN];
131 if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
132 SNPRINTF(offset_str, "%.1f%%", RNA_float_get(op->ptr, "offset_pct"));
133 }
134 else {
135 double offset_val = double(RNA_float_get(op->ptr, "offset"));
137 offset_str, NUM_STR_REP_LEN, offset_val, 3, B_UNIT_LENGTH, sce->unit, true);
138 }
139
140 PropertyRNA *prop;
141 const char *mode_str, *omiter_str, *imiter_str, *vmesh_str, *profile_type_str, *affect_str;
142 prop = RNA_struct_find_property(op->ptr, "offset_type");
144 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &mode_str);
145
146 /* Shown in area header. */
147
148 const std::string header_status = fmt::format("{}: {}, {}: {}, {}: {}",
149 mode_str,
150 offset_str,
151 IFACE_("Segments"),
152 RNA_int_get(op->ptr, "segments"),
153 IFACE_("Profile Shape"),
154 RNA_float_get(op->ptr, "profile"));
155
156 ED_area_status_text(CTX_wm_area(C), header_status.c_str());
157
158 /* Shown on Status Bar. */
159
160 prop = RNA_struct_find_property(op->ptr, "profile_type");
162 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &profile_type_str);
163 prop = RNA_struct_find_property(op->ptr, "miter_outer");
165 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &omiter_str);
166 prop = RNA_struct_find_property(op->ptr, "miter_inner");
168 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &imiter_str);
169 prop = RNA_struct_find_property(op->ptr, "vmesh_method");
171 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &vmesh_str);
172 prop = RNA_struct_find_property(op->ptr, "affect");
174 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &affect_str);
175
176 WorkspaceStatus status(C);
177 status.opmodal(IFACE_("Confirm"), op->type, BEV_MODAL_CONFIRM);
178 status.opmodal(IFACE_("Cancel"), op->type, BEV_MODAL_CANCEL);
179 status.opmodal(IFACE_("Width Type"), op->type, BEV_MODAL_OFFSET_MODE_CHANGE);
180
181 status.opmodal(
182 IFACE_("Width"), op->type, BEV_MODAL_VALUE_OFFSET, opdata->value_mode == OFFSET_VALUE);
183 status.opmodal(IFACE_("Segments"),
184 op->type,
186 opdata->value_mode == SEGMENTS_VALUE);
187 status.opmodal(IFACE_("Profile Shape"),
188 op->type,
190 opdata->value_mode == PROFILE_VALUE);
191
192 status.opmodal(IFACE_("Clamp"),
193 op->type,
195 RNA_boolean_get(op->ptr, "clamp_overlap"));
196 status.opmodal(IFACE_("Harden"),
197 op->type,
199 RNA_boolean_get(op->ptr, "harden_normals"));
200 status.opmodal(
201 IFACE_("Seam"), op->type, BEV_MODAL_MARK_SEAM_TOGGLE, RNA_boolean_get(op->ptr, "mark_seam"));
202 status.opmodal(IFACE_("Sharp"),
203 op->type,
205 RNA_boolean_get(op->ptr, "mark_sharp"));
206
207 std::string desc;
208
209 desc = fmt::format("{} ({}) ", IFACE_("Affect"), affect_str);
210 status.opmodal(desc, op->type, BEV_MODAL_AFFECT_CHANGE);
211
212 desc = fmt::format("{} ({}) ", IFACE_("Outer"), omiter_str);
213 status.opmodal(desc, op->type, BEV_MODAL_OUTER_MITER_CHANGE);
214
215 desc = fmt::format("{} ({}) ", IFACE_("Inner"), imiter_str);
216 status.opmodal(desc, op->type, BEV_MODAL_INNER_MITER_CHANGE);
217
218 desc = fmt::format("{} ({}) ", IFACE_("Profile Type"), profile_type_str);
219 status.opmodal(desc, op->type, BEV_MODAL_PROFILE_TYPE_CHANGE);
220
221 desc = fmt::format("{} ({}) ", IFACE_("Intersection"), vmesh_str);
222 status.opmodal(desc, op->type, BEV_MODAL_VERTEX_MESH_CHANGE);
223}
224
225static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
226{
227 Scene *scene = CTX_data_scene(C);
228 View3D *v3d = CTX_wm_view3d(C);
230 ViewLayer *view_layer = CTX_data_view_layer(C);
231
232 if (is_modal) {
233 RNA_float_set(op->ptr, "offset", 0.0f);
234 RNA_float_set(op->ptr, "offset_pct", 0.0f);
235 }
236
237 op->customdata = MEM_new<BevelData>(__func__);
238 BevelData *opdata = static_cast<BevelData *>(op->customdata);
239 opdata->max_obj_scale = FLT_MIN;
240
241 /* Put the Curve Profile from the toolsettings into the opdata struct */
243
244 {
246 scene, view_layer, v3d);
247 for (Object *obedit : objects) {
248 float scale = mat4_to_scale(obedit->object_to_world().ptr());
249 opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
251 if (em->bm->totvertsel > 0) {
252 opdata->ob_store.append(BevelObjectStore{obedit, {}});
253 }
254 }
255 }
256
257 opdata->is_modal = is_modal;
258 int otype = RNA_enum_get(op->ptr, "offset_type");
260 opdata->segments = float(RNA_int_get(op->ptr, "segments"));
261 float pixels_per_inch = U.dpi;
262
263 for (int i = 0; i < NUM_VALUE_KINDS; i++) {
264 opdata->shift_value[i] = -1.0f;
265 opdata->initial_length[i] = -1.0f;
266 /* NOTE: scale for #OFFSET_VALUE will get overwritten in #edbm_bevel_invoke. */
267 opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
268
269 initNumInput(&opdata->num_input[i]);
270 opdata->num_input[i].idx_max = 0;
271 opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
272 opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
273 if (i == SEGMENTS_VALUE) {
275 }
276 if (i == OFFSET_VALUE) {
277 opdata->num_input[i].unit_sys = scene->unit.system;
278 opdata->num_input[i].unit_type[0] = B_UNIT_LENGTH;
279 }
280 }
281
282 /* avoid the cost of allocating a bm copy */
283 if (is_modal) {
284 ARegion *region = CTX_wm_region(C);
285
286 for (BevelObjectStore &ob_store : opdata->ob_store) {
287 Object *obedit = ob_store.ob;
289 ob_store.mesh_backup = EDBM_redo_state_store(em);
290 }
293 opdata->mcenter,
295 G.moving = G_TRANSFORM_EDIT;
296 }
297
298 return true;
299}
300
302{
303 BevelData *opdata = static_cast<BevelData *>(op->customdata);
304 BMOperator bmop;
305 bool changed = false;
306
307 const float offset = get_bevel_offset(op);
308 const int offset_type = RNA_enum_get(op->ptr, "offset_type");
309 const int profile_type = RNA_enum_get(op->ptr, "profile_type");
310 const int segments = RNA_int_get(op->ptr, "segments");
311 const float profile = RNA_float_get(op->ptr, "profile");
312 const bool affect = RNA_enum_get(op->ptr, "affect");
313 const bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
314 const int material_init = RNA_int_get(op->ptr, "material");
315 const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
316 const bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
317 const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
318 const bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
319 const int face_strength_mode = RNA_enum_get(op->ptr, "face_strength_mode");
320 const int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
321 const int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
322 const float spread = RNA_float_get(op->ptr, "spread");
323 const int vmesh_method = RNA_enum_get(op->ptr, "vmesh_method");
324
325 for (BevelObjectStore &ob_store : opdata->ob_store) {
326 Object *obedit = ob_store.ob;
328
329 /* revert to original mesh */
330 if (opdata->is_modal) {
331 EDBM_redo_state_restore(&ob_store.mesh_backup, em, false);
332 }
333
334 const int material = std::clamp(material_init, -1, obedit->totcol - 1);
335
336 EDBM_op_init(em,
337 &bmop,
338 op,
339 "bevel geom=%hev offset=%f segments=%i affect=%i offset_type=%i "
340 "profile_type=%i profile=%f clamp_overlap=%b material=%i loop_slide=%b "
341 "mark_seam=%b mark_sharp=%b harden_normals=%b face_strength_mode=%i "
342 "miter_outer=%i miter_inner=%i spread=%f custom_profile=%p "
343 "vmesh_method=%i",
345 offset,
346 segments,
347 affect,
348 offset_type,
349 profile_type,
350 profile,
351 clamp_overlap,
352 material,
353 loop_slide,
354 mark_seam,
355 mark_sharp,
356 harden_normals,
357 face_strength_mode,
358 miter_outer,
359 miter_inner,
360 spread,
361 opdata->custom_profile,
362 vmesh_method);
363
364 BMO_op_exec(em->bm, &bmop);
365
366 if (offset != 0.0f) {
367 /* Not essential, but we may have some loose geometry that
368 * won't get beveled and better not leave it selected. */
371 em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
372 if (affect == BEVEL_AFFECT_VERTICES) {
374 em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
376 em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
377
378 if ((em->bm->selectmode & SCE_SELECT_VERTEX) == 0) {
380 }
381 }
382 }
383
384 /* no need to de-select existing geometry */
385 if (!EDBM_op_finish(em, &bmop, op, true)) {
386 continue;
387 }
388
390 params.calc_looptris = true;
391 params.calc_normals = true;
392 params.is_destructive = true;
393 EDBM_update(static_cast<Mesh *>(obedit->data), &params);
394 changed = true;
395 }
396 return changed;
397}
398
400{
401 BevelData *opdata = static_cast<BevelData *>(op->customdata);
402 ScrArea *area = CTX_wm_area(C);
403
404 if (area) {
405 ED_area_status_text(area, nullptr);
406 }
407
408 for (BevelObjectStore &ob_store : opdata->ob_store) {
409 BMEditMesh *em = BKE_editmesh_from_object(ob_store.ob);
410 /* Without this, faces surrounded by selected edges/verts will be unselected. */
411 if ((em->selectmode & SCE_SELECT_FACE) == 0) {
413 }
414 }
415
416 if (opdata->is_modal) {
417 ARegion *region = CTX_wm_region(C);
418 for (BevelObjectStore &ob_store : opdata->ob_store) {
420 }
421 ED_region_draw_cb_exit(region->runtime->type, opdata->draw_handle_pixel);
422 G.moving = 0;
423 }
424 MEM_delete(opdata);
425 op->customdata = nullptr;
426}
427
429{
430 BevelData *opdata = static_cast<BevelData *>(op->customdata);
431 if (opdata->is_modal) {
432 for (BevelObjectStore &ob_store : opdata->ob_store) {
433 Object *obedit = ob_store.ob;
436
438 params.calc_looptris = false;
439 params.calc_normals = true;
440 params.is_destructive = true;
441 EDBM_update(static_cast<Mesh *>(obedit->data), &params);
442 }
443 }
444
445 edbm_bevel_exit(C, op);
446
447 /* Need to force re-display or we may still view the modified result. */
449}
450
451/* bevel! yay!! */
453{
454 if (!edbm_bevel_init(C, op, false)) {
455 return OPERATOR_CANCELLED;
456 }
457
458 if (!edbm_bevel_calc(op)) {
459 edbm_bevel_cancel(C, op);
460 return OPERATOR_CANCELLED;
461 }
462
463 edbm_bevel_exit(C, op);
464
465 return OPERATOR_FINISHED;
466}
467
468static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed)
469{
470 BevelData *opdata = static_cast<BevelData *>(op->customdata);
471 const float mlen[2] = {
472 opdata->mcenter[0] - event->mval[0],
473 opdata->mcenter[1] - event->mval[1],
474 };
475 float len = len_v2(mlen);
476 int vmode = opdata->value_mode;
477 if (mode_changed || opdata->initial_length[vmode] == -1.0f) {
478 /* If current value is not default start value, adjust len so that
479 * the scaling and offset in edbm_bevel_mouse_set_value will
480 * start at current value */
481 float value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
482 RNA_float_get(op->ptr, value_rna_name[vmode]);
483 float sc = opdata->scale[vmode];
484 float st = value_start[vmode];
485 if (value != value_start[vmode]) {
486 len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc;
487 }
488 }
489 opdata->initial_length[opdata->value_mode] = len;
490}
491
493{
495
496 if (!edbm_bevel_init(C, op, true)) {
497 return OPERATOR_CANCELLED;
498 }
499
500 BevelData *opdata = static_cast<BevelData *>(op->customdata);
501
503
504 /* initialize mouse values */
505 float center_3d[3];
507 C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter))
508 {
509 /* in this case the tool will likely do nothing,
510 * ideally this will never happen and should be checked for above */
511 opdata->mcenter[0] = opdata->mcenter[1] = 0;
512 }
513
514 /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */
515 opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
516 /* since we are affecting untransformed object but seeing in transformed space,
517 * compensate for that */
518 opdata->scale[OFFSET_VALUE] /= opdata->max_obj_scale;
519
520 edbm_bevel_calc_initial_length(op, event, false);
521
523
524 if (!edbm_bevel_calc(op)) {
525 edbm_bevel_cancel(C, op);
526 ED_workspace_status_text(C, nullptr);
527 return OPERATOR_CANCELLED;
528 }
529
531
533}
534
535static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
536{
537 BevelData *opdata = static_cast<BevelData *>(op->customdata);
538 int vmode = opdata->value_mode;
539
540 const float mdiff[2] = {
541 opdata->mcenter[0] - event->mval[0],
542 opdata->mcenter[1] - event->mval[1],
543 };
544
545 float value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
546
547 /* Scale according to value mode */
548 value = value_start[vmode] + value * opdata->scale[vmode];
549
550 /* Fake shift-transform... */
551 if (event->modifier & KM_SHIFT) {
552 if (opdata->shift_value[vmode] < 0.0f) {
553 opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ?
554 opdata->segments :
555 RNA_float_get(op->ptr, value_rna_name[vmode]);
556 }
557 value = (value - opdata->shift_value[vmode]) * 0.1f + opdata->shift_value[vmode];
558 }
559 else if (opdata->shift_value[vmode] >= 0.0f) {
560 opdata->shift_value[vmode] = -1.0f;
561 }
562
563 /* Clamp according to value mode, and store value back. */
564 CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
565 if (vmode == SEGMENTS_VALUE) {
566 opdata->segments = value;
567 RNA_int_set(op->ptr, "segments", int(value + 0.5f));
568 }
569 else {
570 RNA_float_set(op->ptr, value_rna_name[vmode], value);
571 }
572}
573
575{
576 BevelData *opdata = static_cast<BevelData *>(op->customdata);
577
578 int vmode = opdata->value_mode;
579 float value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
580 RNA_float_get(op->ptr, value_rna_name[vmode]);
581 applyNumInput(&opdata->num_input[vmode], &value);
582 CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
583 if (vmode == SEGMENTS_VALUE) {
584 opdata->segments = value;
585 RNA_int_set(op->ptr, "segments", int(value));
586 }
587 else {
588 RNA_float_set(op->ptr, value_rna_name[vmode], value);
589 }
590}
591
593{
594 static const EnumPropertyItem modal_items[] = {
595 {BEV_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel bevel"},
596 {BEV_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", "Confirm bevel"},
597 {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Change Offset", "Value changes offset"},
598 {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Change Profile", "Value changes profile"},
599 {BEV_MODAL_VALUE_SEGMENTS, "VALUE_SEGMENTS", 0, "Change Segments", "Value changes segments"},
600 {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase Segments", "Increase segments"},
601 {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease Segments", "Decrease segments"},
603 "OFFSET_MODE_CHANGE",
604 0,
605 "Change Offset Mode",
606 "Cycle through offset modes"},
608 "CLAMP_OVERLAP_TOGGLE",
609 0,
610 "Toggle Clamp Overlap",
611 "Toggle clamp overlap flag"},
613 "AFFECT_CHANGE",
614 0,
615 "Change Affect Type",
616 "Change which geometry type the operation affects, edges or vertices"},
618 "HARDEN_NORMALS_TOGGLE",
619 0,
620 "Toggle Harden Normals",
621 "Toggle harden normals flag"},
623 "MARK_SEAM_TOGGLE",
624 0,
625 "Toggle Mark Seam",
626 "Toggle mark seam flag"},
628 "MARK_SHARP_TOGGLE",
629 0,
630 "Toggle Mark Sharp",
631 "Toggle mark sharp flag"},
633 "OUTER_MITER_CHANGE",
634 0,
635 "Change Outer Miter",
636 "Cycle through outer miter kinds"},
638 "INNER_MITER_CHANGE",
639 0,
640 "Change Inner Miter",
641 "Cycle through inner miter kinds"},
642 {BEV_MODAL_PROFILE_TYPE_CHANGE, "PROFILE_TYPE_CHANGE", 0, "Cycle through profile types", ""},
644 "VERTEX_MESH_CHANGE",
645 0,
646 "Change Intersection Method",
647 "Cycle through intersection methods"},
648 {0, nullptr, 0, nullptr, nullptr},
649 };
650
651 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Bevel Modal Map");
652
653 /* This function is called for each space-type, only needs to add map once. */
654 if (keymap && keymap->modal_items) {
655 return nullptr;
656 }
657
658 keymap = WM_modalkeymap_ensure(keyconf, "Bevel Modal Map", modal_items);
659
660 WM_modalkeymap_assign(keymap, "MESH_OT_bevel");
661
662 return keymap;
663}
664
666{
667 BevelData *opdata = static_cast<BevelData *>(op->customdata);
668 const bool has_numinput = hasNumInput(&opdata->num_input[opdata->value_mode]);
669 bool handled = false;
670 short etype = event->type;
671 short eval = event->val;
672
673 /* When activated from toolbar, need to convert left-mouse release to confirm. */
674 if (ELEM(etype, LEFTMOUSE, opdata->launch_event) && (eval == KM_RELEASE) &&
675 RNA_boolean_get(op->ptr, "release_confirm"))
676 {
677 etype = EVT_MODAL_MAP;
678 eval = BEV_MODAL_CONFIRM;
679 }
680 /* Modal numinput active, try to handle numeric inputs first... */
681 if (etype != EVT_MODAL_MAP && eval == KM_PRESS && has_numinput &&
682 handleNumInput(C, &opdata->num_input[opdata->value_mode], event))
683 {
685 edbm_bevel_calc(op);
688 }
689 if (etype == MOUSEMOVE) {
690 if (!has_numinput) {
692 edbm_bevel_calc(op);
694 handled = true;
695 }
696 }
697 else if (etype == MOUSEPAN) {
698 float delta = 0.02f * (event->xy[1] - event->prev_xy[1]);
699 if (opdata->segments >= 1 && opdata->segments + delta < 1) {
700 opdata->segments = 1;
701 }
702 else {
703 opdata->segments += delta;
704 }
705 RNA_int_set(op->ptr, "segments", int(opdata->segments));
706 edbm_bevel_calc(op);
708 handled = true;
709 }
710 else if (etype == EVT_MODAL_MAP) {
711 switch (eval) {
712 case BEV_MODAL_CANCEL:
713 edbm_bevel_cancel(C, op);
714 ED_workspace_status_text(C, nullptr);
715 return OPERATOR_CANCELLED;
716
718 edbm_bevel_calc(op);
719 edbm_bevel_exit(C, op);
720 ED_workspace_status_text(C, nullptr);
721 return OPERATOR_FINISHED;
722
724 opdata->segments = opdata->segments + 1;
725 RNA_int_set(op->ptr, "segments", int(opdata->segments));
726 edbm_bevel_calc(op);
728 handled = true;
729 break;
730
732 opdata->segments = max_ff(opdata->segments - 1, 1);
733 RNA_int_set(op->ptr, "segments", int(opdata->segments));
734 edbm_bevel_calc(op);
736 handled = true;
737 break;
738
740 int type = RNA_enum_get(op->ptr, "offset_type");
741 type++;
742 if (type > BEVEL_AMT_PERCENT) {
743 type = BEVEL_AMT_OFFSET;
744 }
745 if (opdata->value_mode == OFFSET_VALUE && type == BEVEL_AMT_PERCENT) {
747 }
748 else if (opdata->value_mode == OFFSET_VALUE_PERCENT && type != BEVEL_AMT_PERCENT) {
749 opdata->value_mode = OFFSET_VALUE;
750 }
751 RNA_enum_set(op->ptr, "offset_type", type);
752 if (opdata->initial_length[opdata->value_mode] == -1.0f) {
753 edbm_bevel_calc_initial_length(op, event, true);
754 }
755 }
756 /* Update offset accordingly to new offset_type. */
757 if (!has_numinput && ELEM(opdata->value_mode, OFFSET_VALUE, OFFSET_VALUE_PERCENT)) {
759 }
760 edbm_bevel_calc(op);
762 handled = true;
763 break;
764
766 bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
767 RNA_boolean_set(op->ptr, "clamp_overlap", !clamp_overlap);
768 edbm_bevel_calc(op);
770 handled = true;
771 break;
772 }
773
775 opdata->value_mode = OFFSET_VALUE;
776 edbm_bevel_calc_initial_length(op, event, true);
777 break;
778
780 opdata->value_mode = PROFILE_VALUE;
781 edbm_bevel_calc_initial_length(op, event, true);
782 break;
783
785 opdata->value_mode = SEGMENTS_VALUE;
786 edbm_bevel_calc_initial_length(op, event, true);
787 break;
788
790 int affect_type = RNA_enum_get(op->ptr, "affect");
791 affect_type++;
792 if (affect_type > BEVEL_AFFECT_EDGES) {
793 affect_type = BEVEL_AFFECT_VERTICES;
794 }
795 RNA_enum_set(op->ptr, "affect", affect_type);
796 edbm_bevel_calc(op);
798 handled = true;
799 break;
800 }
801
803 bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
804 RNA_boolean_set(op->ptr, "mark_seam", !mark_seam);
805 edbm_bevel_calc(op);
807 handled = true;
808 break;
809 }
810
812 bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
813 RNA_boolean_set(op->ptr, "mark_sharp", !mark_sharp);
814 edbm_bevel_calc(op);
816 handled = true;
817 break;
818 }
819
821 int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
822 miter_inner++;
823 if (miter_inner == BEVEL_MITER_PATCH) {
824 miter_inner++; /* no patch option for inner miter */
825 }
826 if (miter_inner > BEVEL_MITER_ARC) {
827 miter_inner = BEVEL_MITER_SHARP;
828 }
829 RNA_enum_set(op->ptr, "miter_inner", miter_inner);
830 edbm_bevel_calc(op);
832 handled = true;
833 break;
834 }
835
837 int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
838 miter_outer++;
839 if (miter_outer > BEVEL_MITER_ARC) {
840 miter_outer = BEVEL_MITER_SHARP;
841 }
842 RNA_enum_set(op->ptr, "miter_outer", miter_outer);
843 edbm_bevel_calc(op);
845 handled = true;
846 break;
847 }
848
850 bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
851 RNA_boolean_set(op->ptr, "harden_normals", !harden_normals);
852 edbm_bevel_calc(op);
854 handled = true;
855 break;
856 }
857
859 int profile_type = RNA_enum_get(op->ptr, "profile_type");
860 profile_type++;
861 if (profile_type > BEVEL_PROFILE_CUSTOM) {
862 profile_type = BEVEL_PROFILE_SUPERELLIPSE;
863 }
864 RNA_enum_set(op->ptr, "profile_type", profile_type);
865 edbm_bevel_calc(op);
867 handled = true;
868 break;
869 }
870
872 int vmesh_method = RNA_enum_get(op->ptr, "vmesh_method");
873 vmesh_method++;
874 if (vmesh_method > BEVEL_VMESH_CUTOFF) {
875 vmesh_method = BEVEL_VMESH_ADJ;
876 }
877 RNA_enum_set(op->ptr, "vmesh_method", vmesh_method);
878 edbm_bevel_calc(op);
880 handled = true;
881 break;
882 }
883 }
884 }
885
886 /* Modal numinput inactive, try to handle numeric inputs last... */
887 if (!handled && eval == KM_PRESS &&
888 handleNumInput(C, &opdata->num_input[opdata->value_mode], event))
889 {
891 edbm_bevel_calc(op);
894 }
895
897}
898
900{
901 uiLayout *layout = op->layout;
902 uiLayout *col, *row;
903
904 int profile_type = RNA_enum_get(op->ptr, "profile_type");
905 int offset_type = RNA_enum_get(op->ptr, "offset_type");
906 bool affect_type = RNA_enum_get(op->ptr, "affect");
907
908 uiLayoutSetPropSep(layout, true);
909 uiLayoutSetPropDecorate(layout, false);
910
911 row = &layout->row(false);
912 row->prop(op->ptr, "affect", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
913
914 layout->separator();
915
916 layout->prop(op->ptr, "offset_type", UI_ITEM_NONE, std::nullopt, ICON_NONE);
917
918 if (offset_type == BEVEL_AMT_PERCENT) {
919 layout->prop(op->ptr, "offset_pct", UI_ITEM_NONE, std::nullopt, ICON_NONE);
920 }
921 else {
922 layout->prop(op->ptr, "offset", UI_ITEM_NONE, std::nullopt, ICON_NONE);
923 }
924
925 layout->prop(op->ptr, "segments", UI_ITEM_NONE, std::nullopt, ICON_NONE);
927 layout->prop(op->ptr,
928 "profile",
930 (profile_type == BEVEL_PROFILE_SUPERELLIPSE) ? IFACE_("Profile Shape") :
931 IFACE_("Miter Profile Shape"),
932 ICON_NONE);
933 }
934 layout->prop(op->ptr, "material", UI_ITEM_NONE, std::nullopt, ICON_NONE);
935
936 col = &layout->column(true);
937 col->prop(op->ptr, "harden_normals", UI_ITEM_NONE, std::nullopt, ICON_NONE);
938 col->prop(op->ptr, "clamp_overlap", UI_ITEM_NONE, std::nullopt, ICON_NONE);
939 col->prop(op->ptr, "loop_slide", UI_ITEM_NONE, std::nullopt, ICON_NONE);
940
941 col = &layout->column(true, IFACE_("Mark"));
943 col->prop(op->ptr, "mark_seam", UI_ITEM_NONE, IFACE_("Seams"), ICON_NONE);
944 col->prop(op->ptr, "mark_sharp", UI_ITEM_NONE, IFACE_("Sharp"), ICON_NONE);
945
946 layout->separator();
947
948 col = &layout->column(false);
950 col->prop(op->ptr, "miter_outer", UI_ITEM_NONE, IFACE_("Miter Outer"), ICON_NONE);
951 col->prop(op->ptr, "miter_inner", UI_ITEM_NONE, IFACE_("Inner"), ICON_NONE);
952 if (RNA_enum_get(op->ptr, "miter_inner") == BEVEL_MITER_ARC) {
953 col->prop(op->ptr, "spread", UI_ITEM_NONE, std::nullopt, ICON_NONE);
954 }
955
956 layout->separator();
957
958 col = &layout->column(false);
960 col->prop(op->ptr, "vmesh_method", UI_ITEM_NONE, IFACE_("Intersection Type"), ICON_NONE);
961
962 layout->prop(op->ptr, "face_strength_mode", UI_ITEM_NONE, IFACE_("Face Strength"), ICON_NONE);
963
964 layout->separator();
965
966 row = &layout->row(false);
967 row->prop(op->ptr, "profile_type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
968 if (profile_type == BEVEL_PROFILE_CUSTOM) {
969 /* Get an RNA pointer to ToolSettings to give to the curve profile template code. */
970 Scene *scene = CTX_data_scene(C);
971 PointerRNA toolsettings_ptr = RNA_pointer_create_discrete(
972 &scene->id, &RNA_ToolSettings, scene->toolsettings);
973 uiTemplateCurveProfile(layout, &toolsettings_ptr, "custom_bevel_profile_preset");
974 }
975}
976
978{
979 PropertyRNA *prop;
980
981 static const EnumPropertyItem offset_type_items[] = {
982 {BEVEL_AMT_OFFSET, "OFFSET", 0, "Offset", "Amount is offset of new edges from original"},
983 {BEVEL_AMT_WIDTH, "WIDTH", 0, "Width", "Amount is width of new face"},
985 "DEPTH",
986 0,
987 "Depth",
988 "Amount is perpendicular distance from original edge to bevel face"},
989 {BEVEL_AMT_PERCENT, "PERCENT", 0, "Percent", "Amount is percent of adjacent edge length"},
991 "ABSOLUTE",
992 0,
993 "Absolute",
994 "Amount is absolute distance along adjacent edge"},
995 {0, nullptr, 0, nullptr, nullptr},
996 };
997
998 static const EnumPropertyItem prop_profile_type_items[] = {
1000 "SUPERELLIPSE",
1001 0,
1002 "Superellipse",
1003 "The profile can be a concave or convex curve"},
1005 "CUSTOM",
1006 0,
1007 "Custom",
1008 "The profile can be any arbitrary path between its endpoints"},
1009 {0, nullptr, 0, nullptr, nullptr},
1010 };
1011
1012 static const EnumPropertyItem face_strength_mode_items[] = {
1013 {BEVEL_FACE_STRENGTH_NONE, "NONE", 0, "None", "Do not set face strength"},
1014 {BEVEL_FACE_STRENGTH_NEW, "NEW", 0, "New", "Set face strength on new faces only"},
1016 "AFFECTED",
1017 0,
1018 "Affected",
1019 "Set face strength on new and modified faces only"},
1020 {BEVEL_FACE_STRENGTH_ALL, "ALL", 0, "All", "Set face strength on all faces"},
1021 {0, nullptr, 0, nullptr, nullptr},
1022 };
1023
1024 static const EnumPropertyItem miter_outer_items[] = {
1025 {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Outside of miter is sharp"},
1026 {BEVEL_MITER_PATCH, "PATCH", 0, "Patch", "Outside of miter is squared-off patch"},
1027 {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Outside of miter is arc"},
1028 {0, nullptr, 0, nullptr, nullptr},
1029 };
1030
1031 static const EnumPropertyItem miter_inner_items[] = {
1032 {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Inside of miter is sharp"},
1033 {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Inside of miter is arc"},
1034 {0, nullptr, 0, nullptr, nullptr},
1035 };
1036
1037 static const EnumPropertyItem vmesh_method_items[] = {
1038 {BEVEL_VMESH_ADJ, "ADJ", 0, "Grid Fill", "Default patterned fill"},
1040 "CUTOFF",
1041 0,
1042 "Cutoff",
1043 "A cutoff at each profile's end before the intersection"},
1044 {0, nullptr, 0, nullptr, nullptr},
1045 };
1046
1047 static const EnumPropertyItem prop_affect_items[] = {
1048 {BEVEL_AFFECT_VERTICES, "VERTICES", 0, "Vertices", "Affect only vertices"},
1049 {BEVEL_AFFECT_EDGES, "EDGES", 0, "Edges", "Affect only edges"},
1050 {0, nullptr, 0, nullptr, nullptr},
1051 };
1052
1053 /* identifiers */
1054 ot->name = "Bevel";
1055 ot->description = "Cut into selected items at an angle to create bevel or chamfer";
1056 ot->idname = "MESH_OT_bevel";
1057
1058 /* API callbacks. */
1059 ot->exec = edbm_bevel_exec;
1060 ot->invoke = edbm_bevel_invoke;
1061 ot->modal = edbm_bevel_modal;
1062 ot->cancel = edbm_bevel_cancel;
1063 ot->poll = ED_operator_editmesh;
1064 ot->ui = edbm_bevel_ui;
1065
1066 /* flags */
1068
1069 /* properties */
1070 RNA_def_enum(ot->srna,
1071 "offset_type",
1072 offset_type_items,
1073 0,
1074 "Width Type",
1075 "The method for determining the size of the bevel");
1076 prop = RNA_def_property(ot->srna, "offset", PROP_FLOAT, PROP_DISTANCE);
1077 RNA_def_property_range(prop, 0.0, 1e6);
1078 RNA_def_property_ui_range(prop, 0.0, 100.0, 1, 3);
1079 RNA_def_property_ui_text(prop, "Width", "Bevel amount");
1080
1081 RNA_def_enum(ot->srna,
1082 "profile_type",
1083 prop_profile_type_items,
1084 0,
1085 "Profile Type",
1086 "The type of shape used to rebuild a beveled section");
1087
1088 prop = RNA_def_property(ot->srna, "offset_pct", PROP_FLOAT, PROP_PERCENTAGE);
1089 RNA_def_property_range(prop, 0.0, 100);
1090 RNA_def_property_ui_text(prop, "Width Percent", "Bevel amount for percentage method");
1091
1092 RNA_def_int(ot->srna,
1093 "segments",
1094 1,
1095 1,
1097 "Segments",
1098 "Segments for curved edge",
1099 1,
1100 100);
1101
1102 RNA_def_float(ot->srna,
1103 "profile",
1104 0.5f,
1106 1.0f,
1107 "Profile",
1108 "Controls profile shape (0.5 = round)",
1110 1.0f);
1111
1112 RNA_def_enum(ot->srna,
1113 "affect",
1114 prop_affect_items,
1116 "Affect",
1117 "Affect edges or vertices");
1118
1119 RNA_def_boolean(ot->srna,
1120 "clamp_overlap",
1121 false,
1122 "Clamp Overlap",
1123 "Do not allow beveled edges/vertices to overlap each other");
1124
1126 ot->srna, "loop_slide", true, "Loop Slide", "Prefer sliding along edges to even widths");
1127
1128 RNA_def_boolean(ot->srna, "mark_seam", false, "Mark Seams", "Mark Seams along beveled edges");
1129
1130 RNA_def_boolean(ot->srna, "mark_sharp", false, "Mark Sharp", "Mark beveled edges as sharp");
1131
1132 RNA_def_int(ot->srna,
1133 "material",
1134 -1,
1135 -1,
1136 INT_MAX,
1137 "Material Index",
1138 "Material for bevel faces (-1 means use adjacent faces)",
1139 -1,
1140 100);
1141
1142 RNA_def_boolean(ot->srna,
1143 "harden_normals",
1144 false,
1145 "Harden Normals",
1146 "Match normals of new faces to adjacent faces");
1147
1148 RNA_def_enum(ot->srna,
1149 "face_strength_mode",
1150 face_strength_mode_items,
1152 "Face Strength Mode",
1153 "Whether to set face strength, and which faces to set face strength on");
1154
1155 RNA_def_enum(ot->srna,
1156 "miter_outer",
1157 miter_outer_items,
1159 "Outer Miter",
1160 "Pattern to use for outside of miters");
1161
1162 RNA_def_enum(ot->srna,
1163 "miter_inner",
1164 miter_inner_items,
1166 "Inner Miter",
1167 "Pattern to use for inside of miters");
1168
1169 RNA_def_float(ot->srna,
1170 "spread",
1171 0.1f,
1172 0.0f,
1173 1e6f,
1174 "Spread",
1175 "Amount to spread arcs for arc inner miters",
1176 0.0f,
1177 100.0f);
1178
1179 RNA_def_enum(ot->srna,
1180 "vmesh_method",
1181 vmesh_method_items,
1183 "Vertex Mesh Method",
1184 "The method to use to create meshes at intersections");
1185
1186 prop = RNA_def_boolean(ot->srna, "release_confirm", false, "Confirm on Release", "");
1188}
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ToolSettings * CTX_data_tool_settings(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)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
@ G_TRANSFORM_EDIT
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
size_t BKE_unit_value_as_string_scaled(char *str, int str_maxncpy, double value, int prec, int type, const UnitSettings &settings, bool pad)
Definition unit.cc:1889
@ B_UNIT_LENGTH
Definition BKE_unit.hh:124
@ B_UNIT_NONE
Definition BKE_unit.hh:123
MINLINE float max_ff(float a, float b)
float mat4_to_scale(const float mat[4][4])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
#define CLAMP(a, b, c)
#define ELEM(...)
#define IFACE_(msgid)
Object is a sort of wrapper for general info.
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
@ V3D_AROUND_CENTER_MEDIAN
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void EDBM_flag_disable_all(BMEditMesh *em, char hflag)
void void EDBM_redo_state_restore_and_free(BMBackup *backup, BMEditMesh *em, bool recalc_looptris) ATTR_NONNULL(1
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params)
void void void EDBM_redo_state_free(BMBackup *backup) ATTR_NONNULL(1)
void EDBM_selectmode_flush(BMEditMesh *em)
BMBackup EDBM_redo_state_store(BMEditMesh *em)
void EDBM_redo_state_restore(BMBackup *backup, BMEditMesh *em, bool recalc_looptris) ATTR_NONNULL(1
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
@ NUM_NO_NEGATIVE
@ NUM_NO_ZERO
@ 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
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)
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
#define REGION_DRAW_POST_PIXEL
void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_info)
Definition ed_draw.cc:662
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
Read Guarded memory(de)allocation.
@ PROP_FLOAT
Definition RNA_types.hh:152
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
@ PROP_DISTANCE
Definition RNA_types.hh:244
@ PROP_PERCENTAGE
Definition RNA_types.hh:238
#define C
Definition RandGen.cpp:29
void uiTemplateCurveProfile(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
@ KM_SHIFT
Definition WM_types.hh:275
@ OPTYPE_BLOCKING
Definition WM_types.hh:184
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_GRAB_CURSOR_XY
Definition WM_types.hh:188
@ OPTYPE_REGISTER
Definition WM_types.hh:180
@ KM_PRESS
Definition WM_types.hh:308
@ KM_RELEASE
Definition WM_types.hh:309
#define U
@ BM_ELEM_SELECT
void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode, eBMSelectionFlushFLags flags)
Select Mode Flush.
@ BM_SELECT_LEN_FLUSH_RECALC_EDGE
#define BM_FACE
#define BM_EDGE
#define BM_VERT
void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, char hflag, bool do_flush)
BMO_FLAG_BUFFER.
void BMO_op_exec(BMesh *bm, BMOperator *op)
BMESH OPSTACK EXEC OP.
@ BEVEL_AMT_WIDTH
@ BEVEL_AMT_ABSOLUTE
@ BEVEL_AMT_PERCENT
@ BEVEL_AMT_OFFSET
@ BEVEL_AMT_DEPTH
@ BEVEL_VMESH_ADJ
@ BEVEL_VMESH_CUTOFF
@ BEVEL_PROFILE_SUPERELLIPSE
@ BEVEL_PROFILE_CUSTOM
@ BEVEL_MITER_PATCH
@ BEVEL_MITER_SHARP
@ BEVEL_MITER_ARC
@ BEVEL_AFFECT_VERTICES
@ BEVEL_AFFECT_EDGES
@ BEVEL_FACE_STRENGTH_NONE
@ BEVEL_FACE_STRENGTH_AFFECTED
@ BEVEL_FACE_STRENGTH_NEW
@ BEVEL_FACE_STRENGTH_ALL
void opmodal(std::string text, const wmOperatorType *ot, int propvalue, bool inverted=false)
Definition area.cc:1005
static wmOperatorStatus edbm_bevel_exec(bContext *C, wmOperator *op)
static const float value_clamp_max[NUM_VALUE_KINDS]
static void edbm_bevel_cancel(bContext *C, wmOperator *op)
static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
static void edbm_bevel_ui(bContext *C, wmOperator *op)
static void edbm_bevel_exit(bContext *C, wmOperator *op)
static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
static const float value_start[NUM_VALUE_KINDS]
#define PROFILE_VALUE
static wmOperatorStatus edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
@ BEV_MODAL_CANCEL
@ BEV_MODAL_PROFILE_TYPE_CHANGE
@ BEV_MODAL_MARK_SHARP_TOGGLE
@ BEV_MODAL_AFFECT_CHANGE
@ BEV_MODAL_HARDEN_NORMALS_TOGGLE
@ BEV_MODAL_VERTEX_MESH_CHANGE
@ BEV_MODAL_OFFSET_MODE_CHANGE
@ BEV_MODAL_VALUE_OFFSET
@ BEV_MODAL_SEGMENTS_UP
@ BEV_MODAL_SEGMENTS_DOWN
@ BEV_MODAL_CONFIRM
@ BEV_MODAL_INNER_MITER_CHANGE
@ BEV_MODAL_MARK_SEAM_TOGGLE
@ BEV_MODAL_VALUE_SEGMENTS
@ BEV_MODAL_OUTER_MITER_CHANGE
@ BEV_MODAL_CLAMP_OVERLAP_TOGGLE
@ BEV_MODAL_VALUE_PROFILE
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
static const float value_clamp_min[NUM_VALUE_KINDS]
#define OFFSET_VALUE_PERCENT
static float get_bevel_offset(wmOperator *op)
wmKeyMap * bevel_modal_keymap(wmKeyConfig *keyconf)
static void edbm_bevel_numinput_set_value(wmOperator *op)
void MESH_OT_bevel(wmOperatorType *ot)
static const char * value_rna_name[NUM_VALUE_KINDS]
static wmOperatorStatus edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#define SEGMENTS_HARD_MAX
static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed)
#define OFFSET_VALUE
#define SEGMENTS_VALUE
#define MVAL_PIXEL_MARGIN
#define PROFILE_HARD_MIN
static bool edbm_bevel_calc(wmOperator *op)
#define NUM_VALUE_KINDS
static const float value_scale_per_inch[NUM_VALUE_KINDS]
bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt,...)
bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report)
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define G(x, y, z)
bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2])
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
bool RNA_property_enum_name_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
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)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
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)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_range(PropertyRNA *prop, double min, double max)
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_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double step, int precision)
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)
ARegionRuntimeHandle * runtime
short selectmode
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
int totvertsel
short selectmode
float mcenter[2]
float max_obj_scale
void * draw_handle_pixel
float shift_value[NUM_VALUE_KINDS]
Vector< BevelObjectStore > ob_store
NumInput num_input[NUM_VALUE_KINDS]
CurveProfile * custom_profile
float scale[NUM_VALUE_KINDS]
float initial_length[NUM_VALUE_KINDS]
short idx_max
short val_flag[NUM_MAX_ELEMENTS]
int unit_type[NUM_MAX_ELEMENTS]
struct ToolSettings * toolsettings
struct UnitSettings unit
struct CurveProfile * custom_bevel_profile_preset
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
wmEventModifierFlag modifier
Definition WM_types.hh:771
wmEventType type
Definition WM_types.hh:754
const void * modal_items
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
i
Definition text_draw.cc:230
uint len
int WM_userdef_event_type_from_keymap_type(int kmitype)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ MOUSEPAN
@ EVT_MODAL_MAP
@ MOUSEMOVE
@ LEFTMOUSE
wmOperatorType * ot
Definition wm_files.cc:4225
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:929
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:956