Blender V5.0
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_utf8.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"
37#include "UI_resources.hh"
38
39#include "ED_mesh.hh"
40#include "ED_numinput.hh"
41#include "ED_screen.hh"
42#include "ED_space_api.hh"
43#include "ED_transform.hh"
44#include "ED_util.hh"
45#include "ED_view3d.hh"
46
47#include "mesh_intern.hh" /* own include */
48
49using blender::Vector;
50
51#define MVAL_PIXEL_MARGIN 5.0f
52
53#define PROFILE_HARD_MIN 0.0f
54
55#define SEGMENTS_HARD_MAX 1000
56
57/* which value is mouse movement and numeric input controlling? */
58#define OFFSET_VALUE 0
59#define OFFSET_VALUE_PERCENT 1
60#define PROFILE_VALUE 2
61#define SEGMENTS_VALUE 3
62#define NUM_VALUE_KINDS 4
63
64static const char *value_rna_name[NUM_VALUE_KINDS] = {
65 "offset", "offset_pct", "profile", "segments"};
66static const float value_clamp_min[NUM_VALUE_KINDS] = {0.0f, 0.0f, PROFILE_HARD_MIN, 1.0f};
67static const float value_clamp_max[NUM_VALUE_KINDS] = {1e6, 100.0f, 1.0f, SEGMENTS_HARD_MAX};
68static const float value_start[NUM_VALUE_KINDS] = {0.0f, 0.0f, 0.5f, 1.0f};
69static const float value_scale_per_inch[NUM_VALUE_KINDS] = {0.0f, 100.0f, 1.0f, 4.0f};
70
76
77struct BevelData {
85
87
88 /* modal only */
90 float mcenter[2];
92 short value_mode; /* Which value does mouse movement and numeric input affect? */
93 float segments; /* Segments as float so smooth mouse pan works in small increments */
94
96
99};
100
101enum {
119};
120
122{
123 if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
124 return RNA_float_get(op->ptr, "offset_pct");
125 }
126 return RNA_float_get(op->ptr, "offset");
127}
128
130{
131 Scene *sce = CTX_data_scene(C);
132 BevelData *opdata = static_cast<BevelData *>(op->customdata);
133
134 char offset_str[NUM_STR_REP_LEN];
135 if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
136 SNPRINTF_UTF8(offset_str, "%.1f%%", RNA_float_get(op->ptr, "offset_pct"));
137 }
138 else {
139 double offset_val = double(RNA_float_get(op->ptr, "offset"));
141 offset_str, NUM_STR_REP_LEN, offset_val, -3, B_UNIT_LENGTH, sce->unit, true);
142 }
143
144 PropertyRNA *prop;
145 const char *mode_str, *omiter_str, *imiter_str, *vmesh_str, *profile_type_str, *affect_str;
146 prop = RNA_struct_find_property(op->ptr, "offset_type");
148 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &mode_str);
149
150 /* Shown in area header. */
151
152 const std::string header_status = fmt::format("{}: {}, {}: {}, {}: {}",
153 mode_str,
154 offset_str,
155 IFACE_("Segments"),
156 RNA_int_get(op->ptr, "segments"),
157 IFACE_("Profile Shape"),
158 RNA_float_get(op->ptr, "profile"));
159
160 ED_area_status_text(CTX_wm_area(C), header_status.c_str());
161
162 /* Shown on Status Bar. */
163
164 prop = RNA_struct_find_property(op->ptr, "profile_type");
166 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &profile_type_str);
167 prop = RNA_struct_find_property(op->ptr, "miter_outer");
169 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &omiter_str);
170 prop = RNA_struct_find_property(op->ptr, "miter_inner");
172 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &imiter_str);
173 prop = RNA_struct_find_property(op->ptr, "vmesh_method");
175 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &vmesh_str);
176 prop = RNA_struct_find_property(op->ptr, "affect");
178 C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &affect_str);
179
181 status.opmodal(IFACE_("Confirm"), op->type, BEV_MODAL_CONFIRM);
182 status.opmodal(IFACE_("Cancel"), op->type, BEV_MODAL_CANCEL);
183 status.opmodal(IFACE_("Width Type"), op->type, BEV_MODAL_OFFSET_MODE_CHANGE);
184
185 status.opmodal(
186 IFACE_("Width"), op->type, BEV_MODAL_VALUE_OFFSET, opdata->value_mode == OFFSET_VALUE);
187 status.opmodal(IFACE_("Segments"),
188 op->type,
190 opdata->value_mode == SEGMENTS_VALUE);
191 status.opmodal(IFACE_("Profile Shape"),
192 op->type,
194 opdata->value_mode == PROFILE_VALUE);
195
196 status.opmodal(IFACE_("Clamp"),
197 op->type,
199 RNA_boolean_get(op->ptr, "clamp_overlap"));
200 status.opmodal(IFACE_("Harden"),
201 op->type,
203 RNA_boolean_get(op->ptr, "harden_normals"));
204 status.opmodal(
205 IFACE_("Seam"), op->type, BEV_MODAL_MARK_SEAM_TOGGLE, RNA_boolean_get(op->ptr, "mark_seam"));
206 status.opmodal(IFACE_("Sharp"),
207 op->type,
209 RNA_boolean_get(op->ptr, "mark_sharp"));
210
211 std::string desc;
212
213 desc = fmt::format("{} ({}) ", IFACE_("Affect"), affect_str);
214 status.opmodal(desc, op->type, BEV_MODAL_AFFECT_CHANGE);
215
216 desc = fmt::format("{} ({}) ", IFACE_("Outer"), omiter_str);
217 status.opmodal(desc, op->type, BEV_MODAL_OUTER_MITER_CHANGE);
218
219 desc = fmt::format("{} ({}) ", IFACE_("Inner"), imiter_str);
220 status.opmodal(desc, op->type, BEV_MODAL_INNER_MITER_CHANGE);
221
222 desc = fmt::format("{} ({}) ", IFACE_("Profile Type"), profile_type_str);
223 status.opmodal(desc, op->type, BEV_MODAL_PROFILE_TYPE_CHANGE);
224
225 desc = fmt::format("{} ({}) ", IFACE_("Intersection"), vmesh_str);
226 status.opmodal(desc, op->type, BEV_MODAL_VERTEX_MESH_CHANGE);
227}
228
229static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
230{
231 Scene *scene = CTX_data_scene(C);
232 View3D *v3d = CTX_wm_view3d(C);
234 ViewLayer *view_layer = CTX_data_view_layer(C);
235
236 if (is_modal) {
237 RNA_float_set(op->ptr, "offset", 0.0f);
238 RNA_float_set(op->ptr, "offset_pct", 0.0f);
239 }
240
241 op->customdata = MEM_new<BevelData>(__func__);
242 BevelData *opdata = static_cast<BevelData *>(op->customdata);
243 opdata->max_obj_scale = FLT_MIN;
244
245 /* Put the Curve Profile from the toolsettings into the opdata struct */
247
250
251 {
253 scene, view_layer, v3d);
254 for (Object *obedit : objects) {
255 float scale = mat4_to_scale(obedit->object_to_world().ptr());
256 opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
258 if (em->bm->totvertsel > 0) {
259 opdata->ob_store.append(BevelObjectStore{obedit, {}});
260 }
261 }
262 }
263
264 opdata->is_modal = is_modal;
265 int otype = RNA_enum_get(op->ptr, "offset_type");
267 opdata->segments = float(RNA_int_get(op->ptr, "segments"));
268 float pixels_per_inch = U.dpi;
269
270 for (int i = 0; i < NUM_VALUE_KINDS; i++) {
271 opdata->shift_value[i] = -1.0f;
272 opdata->initial_length[i] = -1.0f;
273 /* NOTE: scale for #OFFSET_VALUE will get overwritten in #edbm_bevel_invoke. */
274 opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
275
276 initNumInput(&opdata->num_input[i]);
277 opdata->num_input[i].idx_max = 0;
278 opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
279 opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
280 if (i == SEGMENTS_VALUE) {
282 }
283 if (i == OFFSET_VALUE) {
284 opdata->num_input[i].unit_sys = scene->unit.system;
285 opdata->num_input[i].unit_type[0] = B_UNIT_LENGTH;
286 }
287 }
288
289 /* avoid the cost of allocating a bm copy */
290 if (is_modal) {
291 ARegion *region = CTX_wm_region(C);
292
293 for (BevelObjectStore &ob_store : opdata->ob_store) {
294 Object *obedit = ob_store.ob;
296 ob_store.mesh_backup = EDBM_redo_state_store(em);
297 }
300 opdata->mcenter,
302 G.moving = G_TRANSFORM_EDIT;
303 }
304
305 return true;
306}
307
309{
310 BevelData *opdata = static_cast<BevelData *>(op->customdata);
311 BMOperator bmop;
312 bool changed_multi = false;
313
314 const float offset = get_bevel_offset(op);
315 const int offset_type = RNA_enum_get(op->ptr, "offset_type");
316 const int profile_type = RNA_enum_get(op->ptr, "profile_type");
317 const int segments = RNA_int_get(op->ptr, "segments");
318 const float profile = RNA_float_get(op->ptr, "profile");
319 const bool affect = RNA_enum_get(op->ptr, "affect");
320 const bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
321 const int material_init = RNA_int_get(op->ptr, "material");
322 const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
323 const bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
324 const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
325 const bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
326 const int face_strength_mode = RNA_enum_get(op->ptr, "face_strength_mode");
327 const int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
328 const int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
329 const float spread = RNA_float_get(op->ptr, "spread");
330 const int vmesh_method = RNA_enum_get(op->ptr, "vmesh_method");
331
332 for (BevelObjectStore &ob_store : opdata->ob_store) {
333 Object *obedit = ob_store.ob;
335
336 /* revert to original mesh */
337 if (opdata->is_modal) {
338 EDBM_redo_state_restore(&ob_store.mesh_backup, em, false);
339 }
340
341 const int material = std::clamp(material_init, -1, obedit->totcol - 1);
342
343 EDBM_op_init(em,
344 &bmop,
345 op,
346 "bevel geom=%hev offset=%f segments=%i affect=%i offset_type=%i "
347 "profile_type=%i profile=%f clamp_overlap=%b material=%i loop_slide=%b "
348 "mark_seam=%b mark_sharp=%b harden_normals=%b face_strength_mode=%i "
349 "miter_outer=%i miter_inner=%i spread=%f custom_profile=%p "
350 "vmesh_method=%i",
352 offset,
353 segments,
354 affect,
355 offset_type,
356 profile_type,
357 profile,
358 clamp_overlap,
359 material,
360 loop_slide,
361 mark_seam,
362 mark_sharp,
363 harden_normals,
364 face_strength_mode,
365 miter_outer,
366 miter_inner,
367 spread,
368 opdata->custom_profile,
369 vmesh_method);
370
371 BMO_op_exec(em->bm, &bmop);
372
373 if (offset != 0.0f) {
374 /* Not essential, but we may have some loose geometry that
375 * won't get beveled and better not leave it selected. */
378 em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
379 if (affect == BEVEL_AFFECT_VERTICES) {
381 em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
383 em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
384
385 if ((em->bm->selectmode & SCE_SELECT_VERTEX) == 0) {
388 }
389 }
390 }
391
392 bool changed = false;
393
394 if (opdata->use_automerge) {
395 changed |= EDBM_automerge_connected(
396 obedit, false, BM_ELEM_SELECT, opdata->automerge_threshold);
397 }
398
399 changed |= EDBM_op_finish(em, &bmop, op, true);
400
401 /* no need to de-select existing geometry */
402 if (changed) {
404 params.calc_looptris = true;
405 params.calc_normals = true;
406 params.is_destructive = true;
407 EDBM_update(static_cast<Mesh *>(obedit->data), &params);
408 }
409
410 changed_multi |= changed;
411 }
412 return changed_multi;
413}
414
416{
417 BevelData *opdata = static_cast<BevelData *>(op->customdata);
418 ScrArea *area = CTX_wm_area(C);
419
420 if (area) {
421 ED_area_status_text(area, nullptr);
422 }
423
424 for (BevelObjectStore &ob_store : opdata->ob_store) {
425 BMEditMesh *em = BKE_editmesh_from_object(ob_store.ob);
426 /* Without this, faces surrounded by selected edges/verts will be unselected. */
427 if ((em->selectmode & SCE_SELECT_FACE) == 0) {
429 }
431 }
432
433 if (opdata->is_modal) {
434 ARegion *region = CTX_wm_region(C);
435 for (BevelObjectStore &ob_store : opdata->ob_store) {
437 }
438 ED_region_draw_cb_exit(region->runtime->type, opdata->draw_handle_pixel);
439 G.moving = 0;
440 }
441 MEM_delete(opdata);
442 op->customdata = nullptr;
443}
444
446{
447 BevelData *opdata = static_cast<BevelData *>(op->customdata);
448 if (opdata->is_modal) {
449 for (BevelObjectStore &ob_store : opdata->ob_store) {
450 Object *obedit = ob_store.ob;
453
455 params.calc_looptris = false;
456 params.calc_normals = true;
457 params.is_destructive = true;
458 EDBM_update(static_cast<Mesh *>(obedit->data), &params);
459 }
460 }
461
462 edbm_bevel_exit(C, op);
463
464 /* Need to force re-display or we may still view the modified result. */
466}
467
468/* bevel! yay!! */
470{
471 if (!edbm_bevel_init(C, op, false)) {
472 return OPERATOR_CANCELLED;
473 }
474
475 if (!edbm_bevel_calc(op)) {
476 edbm_bevel_cancel(C, op);
477 return OPERATOR_CANCELLED;
478 }
479
480 edbm_bevel_exit(C, op);
481
482 return OPERATOR_FINISHED;
483}
484
485static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed)
486{
487 BevelData *opdata = static_cast<BevelData *>(op->customdata);
488 const float mlen[2] = {
489 opdata->mcenter[0] - event->mval[0],
490 opdata->mcenter[1] - event->mval[1],
491 };
492 float len = len_v2(mlen);
493 int vmode = opdata->value_mode;
494 if (mode_changed || opdata->initial_length[vmode] == -1.0f) {
495 /* If current value is not default start value, adjust len so that
496 * the scaling and offset in edbm_bevel_mouse_set_value will
497 * start at current value */
498 float value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
499 RNA_float_get(op->ptr, value_rna_name[vmode]);
500 float sc = opdata->scale[vmode];
501 float st = value_start[vmode];
502 if (value != value_start[vmode]) {
503 len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc;
504 }
505 }
506 opdata->initial_length[opdata->value_mode] = len;
507}
508
510{
512
513 if (!edbm_bevel_init(C, op, true)) {
514 return OPERATOR_CANCELLED;
515 }
516
517 BevelData *opdata = static_cast<BevelData *>(op->customdata);
518
520
521 /* initialize mouse values */
522 float center_3d[3];
524 C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter))
525 {
526 /* in this case the tool will likely do nothing,
527 * ideally this will never happen and should be checked for above */
528 opdata->mcenter[0] = opdata->mcenter[1] = 0;
529 }
530
531 /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */
532 opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
533 /* since we are affecting untransformed object but seeing in transformed space,
534 * compensate for that */
535 opdata->scale[OFFSET_VALUE] /= opdata->max_obj_scale;
536
537 edbm_bevel_calc_initial_length(op, event, false);
538
540
541 if (!edbm_bevel_calc(op)) {
542 edbm_bevel_cancel(C, op);
543 ED_workspace_status_text(C, nullptr);
544 return OPERATOR_CANCELLED;
545 }
546
548
550}
551
552static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
553{
554 BevelData *opdata = static_cast<BevelData *>(op->customdata);
555 int vmode = opdata->value_mode;
556
557 const float mdiff[2] = {
558 opdata->mcenter[0] - event->mval[0],
559 opdata->mcenter[1] - event->mval[1],
560 };
561
562 float value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
563
564 /* Scale according to value mode */
565 value = value_start[vmode] + value * opdata->scale[vmode];
566
567 /* Fake shift-transform... */
568 if (event->modifier & KM_SHIFT) {
569 if (opdata->shift_value[vmode] < 0.0f) {
570 opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ?
571 opdata->segments :
572 RNA_float_get(op->ptr, value_rna_name[vmode]);
573 }
574 value = (value - opdata->shift_value[vmode]) * 0.1f + opdata->shift_value[vmode];
575 }
576 else if (opdata->shift_value[vmode] >= 0.0f) {
577 opdata->shift_value[vmode] = -1.0f;
578 }
579
580 /* Clamp according to value mode, and store value back. */
581 CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
582 if (vmode == SEGMENTS_VALUE) {
583 opdata->segments = value;
584 RNA_int_set(op->ptr, "segments", int(value + 0.5f));
585 }
586 else {
587 RNA_float_set(op->ptr, value_rna_name[vmode], value);
588 }
589}
590
592{
593 BevelData *opdata = static_cast<BevelData *>(op->customdata);
594
595 int vmode = opdata->value_mode;
596 float value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
597 RNA_float_get(op->ptr, value_rna_name[vmode]);
598 applyNumInput(&opdata->num_input[vmode], &value);
599 CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
600 if (vmode == SEGMENTS_VALUE) {
601 opdata->segments = value;
602 RNA_int_set(op->ptr, "segments", int(value));
603 }
604 else {
605 RNA_float_set(op->ptr, value_rna_name[vmode], value);
606 }
607}
608
610{
611 static const EnumPropertyItem modal_items[] = {
612 {BEV_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel bevel"},
613 {BEV_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", "Confirm bevel"},
614 {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Change Offset", "Value changes offset"},
615 {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Change Profile", "Value changes profile"},
616 {BEV_MODAL_VALUE_SEGMENTS, "VALUE_SEGMENTS", 0, "Change Segments", "Value changes segments"},
617 {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase Segments", "Increase segments"},
618 {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease Segments", "Decrease segments"},
620 "OFFSET_MODE_CHANGE",
621 0,
622 "Change Offset Mode",
623 "Cycle through offset modes"},
625 "CLAMP_OVERLAP_TOGGLE",
626 0,
627 "Toggle Clamp Overlap",
628 "Toggle clamp overlap flag"},
630 "AFFECT_CHANGE",
631 0,
632 "Change Affect Type",
633 "Change which geometry type the operation affects, edges or vertices"},
635 "HARDEN_NORMALS_TOGGLE",
636 0,
637 "Toggle Harden Normals",
638 "Toggle harden normals flag"},
640 "MARK_SEAM_TOGGLE",
641 0,
642 "Toggle Mark Seam",
643 "Toggle mark seam flag"},
645 "MARK_SHARP_TOGGLE",
646 0,
647 "Toggle Mark Sharp",
648 "Toggle mark sharp flag"},
650 "OUTER_MITER_CHANGE",
651 0,
652 "Change Outer Miter",
653 "Cycle through outer miter kinds"},
655 "INNER_MITER_CHANGE",
656 0,
657 "Change Inner Miter",
658 "Cycle through inner miter kinds"},
659 {BEV_MODAL_PROFILE_TYPE_CHANGE, "PROFILE_TYPE_CHANGE", 0, "Cycle through profile types", ""},
661 "VERTEX_MESH_CHANGE",
662 0,
663 "Change Intersection Method",
664 "Cycle through intersection methods"},
665 {0, nullptr, 0, nullptr, nullptr},
666 };
667
668 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Bevel Modal Map");
669
670 /* This function is called for each space-type, only needs to add map once. */
671 if (keymap && keymap->modal_items) {
672 return nullptr;
673 }
674
675 keymap = WM_modalkeymap_ensure(keyconf, "Bevel Modal Map", modal_items);
676
677 WM_modalkeymap_assign(keymap, "MESH_OT_bevel");
678
679 return keymap;
680}
681
683{
684 BevelData *opdata = static_cast<BevelData *>(op->customdata);
685 const bool has_numinput = hasNumInput(&opdata->num_input[opdata->value_mode]);
686 bool handled = false;
687 short etype = event->type;
688 short eval = event->val;
689
690 /* When activated from toolbar, need to convert left-mouse release to confirm. */
691 if (ELEM(etype, LEFTMOUSE, opdata->launch_event) && (eval == KM_RELEASE) &&
692 RNA_boolean_get(op->ptr, "release_confirm"))
693 {
694 etype = EVT_MODAL_MAP;
695 eval = BEV_MODAL_CONFIRM;
696 }
697 /* Modal numinput active, try to handle numeric inputs first... */
698 if (etype != EVT_MODAL_MAP && eval == KM_PRESS && has_numinput &&
699 handleNumInput(C, &opdata->num_input[opdata->value_mode], event))
700 {
702 edbm_bevel_calc(op);
705 }
706 if (etype == MOUSEMOVE) {
707 if (!has_numinput) {
709 edbm_bevel_calc(op);
711 handled = true;
712 }
713 }
714 else if (etype == MOUSEPAN) {
715 float delta = 0.02f * (event->xy[1] - event->prev_xy[1]);
716 if (opdata->segments >= 1 && opdata->segments + delta < 1) {
717 opdata->segments = 1;
718 }
719 else {
720 opdata->segments += delta;
721 }
722 RNA_int_set(op->ptr, "segments", int(opdata->segments));
723 edbm_bevel_calc(op);
725 handled = true;
726 }
727 else if (etype == EVT_MODAL_MAP) {
728 switch (eval) {
729 case BEV_MODAL_CANCEL:
730 edbm_bevel_cancel(C, op);
731 ED_workspace_status_text(C, nullptr);
732 return OPERATOR_CANCELLED;
733
735 edbm_bevel_calc(op);
736 edbm_bevel_exit(C, op);
737 ED_workspace_status_text(C, nullptr);
738 return OPERATOR_FINISHED;
739
741 opdata->segments = opdata->segments + 1;
742 RNA_int_set(op->ptr, "segments", int(opdata->segments));
743 edbm_bevel_calc(op);
745 handled = true;
746 break;
747
749 opdata->segments = max_ff(opdata->segments - 1, 1);
750 RNA_int_set(op->ptr, "segments", int(opdata->segments));
751 edbm_bevel_calc(op);
753 handled = true;
754 break;
755
757 int type = RNA_enum_get(op->ptr, "offset_type");
758 type++;
759 if (type > BEVEL_AMT_PERCENT) {
760 type = BEVEL_AMT_OFFSET;
761 }
762 if (opdata->value_mode == OFFSET_VALUE && type == BEVEL_AMT_PERCENT) {
764 }
765 else if (opdata->value_mode == OFFSET_VALUE_PERCENT && type != BEVEL_AMT_PERCENT) {
766 opdata->value_mode = OFFSET_VALUE;
767 }
768 RNA_enum_set(op->ptr, "offset_type", type);
769 if (opdata->initial_length[opdata->value_mode] == -1.0f) {
770 edbm_bevel_calc_initial_length(op, event, true);
771 }
772 }
773 /* Update offset accordingly to new offset_type. */
774 if (!has_numinput && ELEM(opdata->value_mode, OFFSET_VALUE, OFFSET_VALUE_PERCENT)) {
776 }
777 edbm_bevel_calc(op);
779 handled = true;
780 break;
781
783 bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
784 RNA_boolean_set(op->ptr, "clamp_overlap", !clamp_overlap);
785 edbm_bevel_calc(op);
787 handled = true;
788 break;
789 }
790
792 opdata->value_mode = OFFSET_VALUE;
793 edbm_bevel_calc_initial_length(op, event, true);
794 break;
795
797 opdata->value_mode = PROFILE_VALUE;
798 edbm_bevel_calc_initial_length(op, event, true);
799 break;
800
802 opdata->value_mode = SEGMENTS_VALUE;
803 edbm_bevel_calc_initial_length(op, event, true);
804 break;
805
807 int affect_type = RNA_enum_get(op->ptr, "affect");
808 affect_type++;
809 if (affect_type > BEVEL_AFFECT_EDGES) {
810 affect_type = BEVEL_AFFECT_VERTICES;
811 }
812 RNA_enum_set(op->ptr, "affect", affect_type);
813 edbm_bevel_calc(op);
815 handled = true;
816 break;
817 }
818
820 bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
821 RNA_boolean_set(op->ptr, "mark_seam", !mark_seam);
822 edbm_bevel_calc(op);
824 handled = true;
825 break;
826 }
827
829 bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
830 RNA_boolean_set(op->ptr, "mark_sharp", !mark_sharp);
831 edbm_bevel_calc(op);
833 handled = true;
834 break;
835 }
836
838 int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
839 miter_inner++;
840 if (miter_inner == BEVEL_MITER_PATCH) {
841 miter_inner++; /* no patch option for inner miter */
842 }
843 if (miter_inner > BEVEL_MITER_ARC) {
844 miter_inner = BEVEL_MITER_SHARP;
845 }
846 RNA_enum_set(op->ptr, "miter_inner", miter_inner);
847 edbm_bevel_calc(op);
849 handled = true;
850 break;
851 }
852
854 int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
855 miter_outer++;
856 if (miter_outer > BEVEL_MITER_ARC) {
857 miter_outer = BEVEL_MITER_SHARP;
858 }
859 RNA_enum_set(op->ptr, "miter_outer", miter_outer);
860 edbm_bevel_calc(op);
862 handled = true;
863 break;
864 }
865
867 bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
868 RNA_boolean_set(op->ptr, "harden_normals", !harden_normals);
869 edbm_bevel_calc(op);
871 handled = true;
872 break;
873 }
874
876 int profile_type = RNA_enum_get(op->ptr, "profile_type");
877 profile_type++;
878 if (profile_type > BEVEL_PROFILE_CUSTOM) {
879 profile_type = BEVEL_PROFILE_SUPERELLIPSE;
880 }
881 RNA_enum_set(op->ptr, "profile_type", profile_type);
882 edbm_bevel_calc(op);
884 handled = true;
885 break;
886 }
887
889 int vmesh_method = RNA_enum_get(op->ptr, "vmesh_method");
890 vmesh_method++;
891 if (vmesh_method > BEVEL_VMESH_CUTOFF) {
892 vmesh_method = BEVEL_VMESH_ADJ;
893 }
894 RNA_enum_set(op->ptr, "vmesh_method", vmesh_method);
895 edbm_bevel_calc(op);
897 handled = true;
898 break;
899 }
900 }
901 }
902
903 /* Modal numinput inactive, try to handle numeric inputs last... */
904 if (!handled && eval == KM_PRESS &&
905 handleNumInput(C, &opdata->num_input[opdata->value_mode], event))
906 {
908 edbm_bevel_calc(op);
911 }
912
914}
915
917{
918 uiLayout *layout = op->layout;
919 uiLayout *col, *row;
920
921 int profile_type = RNA_enum_get(op->ptr, "profile_type");
922 int offset_type = RNA_enum_get(op->ptr, "offset_type");
923 bool affect_type = RNA_enum_get(op->ptr, "affect");
924
925 layout->use_property_split_set(true);
926 layout->use_property_decorate_set(false);
927
928 row = &layout->row(false);
929 row->prop(op->ptr, "affect", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
930
931 layout->separator();
932
933 layout->prop(op->ptr, "offset_type", UI_ITEM_NONE, std::nullopt, ICON_NONE);
934
935 if (offset_type == BEVEL_AMT_PERCENT) {
936 layout->prop(op->ptr, "offset_pct", UI_ITEM_NONE, std::nullopt, ICON_NONE);
937 }
938 else {
939 layout->prop(op->ptr, "offset", UI_ITEM_NONE, std::nullopt, ICON_NONE);
940 }
941
942 layout->prop(op->ptr, "segments", UI_ITEM_NONE, std::nullopt, ICON_NONE);
944 layout->prop(op->ptr,
945 "profile",
947 (profile_type == BEVEL_PROFILE_SUPERELLIPSE) ? IFACE_("Profile Shape") :
948 IFACE_("Miter Profile Shape"),
949 ICON_NONE);
950 }
951 layout->prop(op->ptr, "material", UI_ITEM_NONE, std::nullopt, ICON_NONE);
952
953 col = &layout->column(true);
954 col->prop(op->ptr, "harden_normals", UI_ITEM_NONE, std::nullopt, ICON_NONE);
955 col->prop(op->ptr, "clamp_overlap", UI_ITEM_NONE, std::nullopt, ICON_NONE);
956 col->prop(op->ptr, "loop_slide", UI_ITEM_NONE, std::nullopt, ICON_NONE);
957
958 col = &layout->column(true, IFACE_("Mark"));
959 col->active_set(affect_type == BEVEL_AFFECT_EDGES);
960 col->prop(op->ptr, "mark_seam", UI_ITEM_NONE, IFACE_("Seams"), ICON_NONE);
961 col->prop(op->ptr, "mark_sharp", UI_ITEM_NONE, IFACE_("Sharp"), ICON_NONE);
962
963 layout->separator();
964
965 col = &layout->column(false);
966 col->active_set(affect_type == BEVEL_AFFECT_EDGES);
967 col->prop(op->ptr, "miter_outer", UI_ITEM_NONE, IFACE_("Miter Outer"), ICON_NONE);
968 col->prop(op->ptr, "miter_inner", UI_ITEM_NONE, IFACE_("Inner"), ICON_NONE);
969 if (RNA_enum_get(op->ptr, "miter_inner") == BEVEL_MITER_ARC) {
970 col->prop(op->ptr, "spread", UI_ITEM_NONE, std::nullopt, ICON_NONE);
971 }
972
973 layout->separator();
974
975 col = &layout->column(false);
976 col->active_set(affect_type == BEVEL_AFFECT_EDGES);
977 col->prop(op->ptr, "vmesh_method", UI_ITEM_NONE, IFACE_("Intersection Type"), ICON_NONE);
978
979 layout->prop(op->ptr, "face_strength_mode", UI_ITEM_NONE, IFACE_("Face Strength"), ICON_NONE);
980
981 layout->separator();
982
983 row = &layout->row(false);
984 row->prop(op->ptr, "profile_type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
985 if (profile_type == BEVEL_PROFILE_CUSTOM) {
986 /* Get an RNA pointer to ToolSettings to give to the curve profile template code. */
987 Scene *scene = CTX_data_scene(C);
988 PointerRNA toolsettings_ptr = RNA_pointer_create_discrete(
989 &scene->id, &RNA_ToolSettings, scene->toolsettings);
990 uiTemplateCurveProfile(layout, &toolsettings_ptr, "custom_bevel_profile_preset");
991 }
992}
993
995{
996 PropertyRNA *prop;
997
998 static const EnumPropertyItem offset_type_items[] = {
999 {BEVEL_AMT_OFFSET, "OFFSET", 0, "Offset", "Amount is offset of new edges from original"},
1000 {BEVEL_AMT_WIDTH, "WIDTH", 0, "Width", "Amount is width of new face"},
1002 "DEPTH",
1003 0,
1004 "Depth",
1005 "Amount is perpendicular distance from original edge to bevel face"},
1006 {BEVEL_AMT_PERCENT, "PERCENT", 0, "Percent", "Amount is percent of adjacent edge length"},
1008 "ABSOLUTE",
1009 0,
1010 "Absolute",
1011 "Amount is absolute distance along adjacent edge"},
1012 {0, nullptr, 0, nullptr, nullptr},
1013 };
1014
1015 static const EnumPropertyItem prop_profile_type_items[] = {
1017 "SUPERELLIPSE",
1018 0,
1019 "Superellipse",
1020 "The profile can be a concave or convex curve"},
1022 "CUSTOM",
1023 0,
1024 "Custom",
1025 "The profile can be any arbitrary path between its endpoints"},
1026 {0, nullptr, 0, nullptr, nullptr},
1027 };
1028
1029 static const EnumPropertyItem face_strength_mode_items[] = {
1030 {BEVEL_FACE_STRENGTH_NONE, "NONE", 0, "None", "Do not set face strength"},
1031 {BEVEL_FACE_STRENGTH_NEW, "NEW", 0, "New", "Set face strength on new faces only"},
1033 "AFFECTED",
1034 0,
1035 "Affected",
1036 "Set face strength on new and modified faces only"},
1037 {BEVEL_FACE_STRENGTH_ALL, "ALL", 0, "All", "Set face strength on all faces"},
1038 {0, nullptr, 0, nullptr, nullptr},
1039 };
1040
1041 static const EnumPropertyItem miter_outer_items[] = {
1042 {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Outside of miter is sharp"},
1043 {BEVEL_MITER_PATCH, "PATCH", 0, "Patch", "Outside of miter is squared-off patch"},
1044 {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Outside of miter is arc"},
1045 {0, nullptr, 0, nullptr, nullptr},
1046 };
1047
1048 static const EnumPropertyItem miter_inner_items[] = {
1049 {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Inside of miter is sharp"},
1050 {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Inside of miter is arc"},
1051 {0, nullptr, 0, nullptr, nullptr},
1052 };
1053
1054 static const EnumPropertyItem vmesh_method_items[] = {
1055 {BEVEL_VMESH_ADJ, "ADJ", 0, "Grid Fill", "Default patterned fill"},
1057 "CUTOFF",
1058 0,
1059 "Cutoff",
1060 "A cutoff at each profile's end before the intersection"},
1061 {0, nullptr, 0, nullptr, nullptr},
1062 };
1063
1064 static const EnumPropertyItem prop_affect_items[] = {
1065 {BEVEL_AFFECT_VERTICES, "VERTICES", 0, "Vertices", "Affect only vertices"},
1066 {BEVEL_AFFECT_EDGES, "EDGES", 0, "Edges", "Affect only edges"},
1067 {0, nullptr, 0, nullptr, nullptr},
1068 };
1069
1070 /* identifiers */
1071 ot->name = "Bevel";
1072 ot->description = "Cut into selected items at an angle to create bevel or chamfer";
1073 ot->idname = "MESH_OT_bevel";
1074
1075 /* API callbacks. */
1076 ot->exec = edbm_bevel_exec;
1077 ot->invoke = edbm_bevel_invoke;
1078 ot->modal = edbm_bevel_modal;
1079 ot->cancel = edbm_bevel_cancel;
1080 ot->poll = ED_operator_editmesh;
1081 ot->ui = edbm_bevel_ui;
1082
1083 /* flags */
1085
1086 /* properties */
1087 RNA_def_enum(ot->srna,
1088 "offset_type",
1089 offset_type_items,
1090 0,
1091 "Width Type",
1092 "The method for determining the size of the bevel");
1093 prop = RNA_def_property(ot->srna, "offset", PROP_FLOAT, PROP_DISTANCE);
1094 RNA_def_property_range(prop, 0.0, 1e6);
1095 RNA_def_property_ui_range(prop, 0.0, 100.0, 1, 3);
1096 RNA_def_property_ui_text(prop, "Width", "Bevel amount");
1097
1098 RNA_def_enum(ot->srna,
1099 "profile_type",
1100 prop_profile_type_items,
1101 0,
1102 "Profile Type",
1103 "The type of shape used to rebuild a beveled section");
1104
1105 prop = RNA_def_property(ot->srna, "offset_pct", PROP_FLOAT, PROP_PERCENTAGE);
1106 RNA_def_property_range(prop, 0.0, 100);
1107 RNA_def_property_ui_text(prop, "Width Percent", "Bevel amount for percentage method");
1108
1109 RNA_def_int(ot->srna,
1110 "segments",
1111 1,
1112 1,
1114 "Segments",
1115 "Segments for curved edge",
1116 1,
1117 100);
1118
1119 RNA_def_float(ot->srna,
1120 "profile",
1121 0.5f,
1123 1.0f,
1124 "Profile",
1125 "Controls profile shape (0.5 = round)",
1127 1.0f);
1128
1129 RNA_def_enum(ot->srna,
1130 "affect",
1131 prop_affect_items,
1133 "Affect",
1134 "Affect edges or vertices");
1135
1136 RNA_def_boolean(ot->srna,
1137 "clamp_overlap",
1138 false,
1139 "Clamp Overlap",
1140 "Do not allow beveled edges/vertices to overlap each other");
1141
1143 ot->srna, "loop_slide", true, "Loop Slide", "Prefer sliding along edges to even widths");
1144
1146 ot->srna, "mark_seam", false, "Mark Seams", "Preserve seams along beveled edges");
1148 ot->srna, "mark_sharp", false, "Mark Sharp", "Preserve sharp edges along beveled edges");
1149
1150 RNA_def_int(ot->srna,
1151 "material",
1152 -1,
1153 -1,
1154 INT_MAX,
1155 "Material Index",
1156 "Material for bevel faces (-1 means use adjacent faces)",
1157 -1,
1158 100);
1159
1160 RNA_def_boolean(ot->srna,
1161 "harden_normals",
1162 false,
1163 "Harden Normals",
1164 "Match normals of new faces to adjacent faces");
1165
1166 RNA_def_enum(ot->srna,
1167 "face_strength_mode",
1168 face_strength_mode_items,
1170 "Face Strength Mode",
1171 "Whether to set face strength, and which faces to set face strength on");
1172
1173 RNA_def_enum(ot->srna,
1174 "miter_outer",
1175 miter_outer_items,
1177 "Outer Miter",
1178 "Pattern to use for outside of miters");
1179
1180 RNA_def_enum(ot->srna,
1181 "miter_inner",
1182 miter_inner_items,
1184 "Inner Miter",
1185 "Pattern to use for inside of miters");
1186
1187 RNA_def_float(ot->srna,
1188 "spread",
1189 0.1f,
1190 0.0f,
1191 1e6f,
1192 "Spread",
1193 "Amount to spread arcs for arc inner miters",
1194 0.0f,
1195 100.0f);
1196
1197 RNA_def_enum(ot->srna,
1198 "vmesh_method",
1199 vmesh_method_items,
1201 "Vertex Mesh Method",
1202 "The method to use to create meshes at intersections");
1203
1204 prop = RNA_def_boolean(ot->srna, "release_confirm", false, "Confirm on Release", "");
1206}
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)
@ B_UNIT_LENGTH
Definition BKE_unit.hh:137
@ B_UNIT_NONE
Definition BKE_unit.hh:136
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:1895
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_UTF8(dst, format,...)
#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
@ AUTO_MERGE
@ 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)
bool EDBM_uvselect_clear(BMEditMesh *em)
void void void EDBM_redo_state_free(BMBackup *backup) ATTR_NONNULL(1)
bool EDBM_automerge_connected(Object *obedit, bool update, char hflag, float dist)
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:70
#define NUM_STR_REP_LEN
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition numinput.cc:312
bool applyNumInput(NumInput *n, float *vec)
Definition numinput.cc:190
@ NUM_NO_NEGATIVE
@ NUM_NO_ZERO
@ NUM_NO_FRACTION
bool hasNumInput(const NumInput *n)
Definition numinput.cc:171
void ED_area_status_text(ScrArea *area, const char *str)
Definition area.cc:851
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1024
bool ED_operator_editmesh(bContext *C)
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:618
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:164
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
@ PROP_HIDDEN
Definition RNA_types.hh:338
@ PROP_DISTANCE
Definition RNA_types.hh:256
@ PROP_PERCENTAGE
Definition RNA_types.hh:250
#define C
Definition RandGen.cpp:29
void uiTemplateCurveProfile(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
#define UI_ITEM_NONE
@ KM_SHIFT
Definition WM_types.hh:278
@ KM_PRESS
Definition WM_types.hh:311
@ KM_RELEASE
Definition WM_types.hh:312
@ 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
#define U
@ BM_ELEM_SELECT
void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode, BMSelectFlushFlag flag)
Select Mode Flush.
#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_MITER_PATCH
@ BEVEL_MITER_SHARP
@ BEVEL_MITER_ARC
@ BEVEL_AMT_WIDTH
@ BEVEL_AMT_ABSOLUTE
@ BEVEL_AMT_PERCENT
@ BEVEL_AMT_OFFSET
@ BEVEL_AMT_DEPTH
@ BEVEL_VMESH_ADJ
@ BEVEL_VMESH_CUTOFF
@ BEVEL_AFFECT_VERTICES
@ BEVEL_AFFECT_EDGES
@ BEVEL_FACE_STRENGTH_NONE
@ BEVEL_FACE_STRENGTH_AFFECTED
@ BEVEL_FACE_STRENGTH_NEW
@ BEVEL_FACE_STRENGTH_ALL
@ BEVEL_PROFILE_SUPERELLIPSE
@ BEVEL_PROFILE_CUSTOM
nullptr float
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)
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)
@ 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
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])
const int status
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
double automerge_threshold
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
void use_property_decorate_set(bool is_sep)
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiLayout & row(bool align)
void use_property_split_set(bool value)
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:774
wmEventType type
Definition WM_types.hh:757
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:4237
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:932
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:959