Blender V4.3
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
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_unit.hh"
26
27#include "RNA_access.hh"
28#include "RNA_define.hh"
29#include "RNA_prototypes.hh"
30
31#include "WM_api.hh"
32#include "WM_types.hh"
33
34#include "UI_interface.hh"
35#include "UI_resources.hh"
36
37#include "ED_mesh.hh"
38#include "ED_numinput.hh"
39#include "ED_screen.hh"
40#include "ED_space_api.hh"
41#include "ED_transform.hh"
42#include "ED_util.hh"
43#include "ED_view3d.hh"
44
45#include "mesh_intern.hh" /* own include */
46
47using blender::Vector;
48
49#define MVAL_PIXEL_MARGIN 5.0f
50
51#define PROFILE_HARD_MIN 0.0f
52
53#define SEGMENTS_HARD_MAX 1000
54
55/* which value is mouse movement and numeric input controlling? */
56#define OFFSET_VALUE 0
57#define OFFSET_VALUE_PERCENT 1
58#define PROFILE_VALUE 2
59#define SEGMENTS_VALUE 3
60#define NUM_VALUE_KINDS 4
61
62static const char *value_rna_name[NUM_VALUE_KINDS] = {
63 "offset", "offset_pct", "profile", "segments"};
64static const float value_clamp_min[NUM_VALUE_KINDS] = {0.0f, 0.0f, PROFILE_HARD_MIN, 1.0f};
65static const float value_clamp_max[NUM_VALUE_KINDS] = {1e6, 100.0f, 1.0f, SEGMENTS_HARD_MAX};
66static const float value_start[NUM_VALUE_KINDS] = {0.0f, 0.0f, 0.5f, 1.0f};
67static const float value_scale_per_inch[NUM_VALUE_KINDS] = {0.0f, 100.0f, 1.0f, 4.0f};
68
74
75struct BevelData {
77 float scale[NUM_VALUE_KINDS];
83
85
86 /* modal only */
88 float mcenter[2];
90 short value_mode; /* Which value does mouse movement and numeric input affect? */
91 float segments; /* Segments as float so smooth mouse pan works in small increments */
92
94};
95
96enum {
114};
115
117{
118 if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
119 return RNA_float_get(op->ptr, "offset_pct");
120 }
121 return RNA_float_get(op->ptr, "offset");
122}
123
125{
126 Scene *sce = CTX_data_scene(C);
127 BevelData *opdata = static_cast<BevelData *>(op->customdata);
128
129 char offset_str[NUM_STR_REP_LEN];
130 if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
131 SNPRINTF(offset_str, "%.1f%%", RNA_float_get(op->ptr, "offset_pct"));
132 }
133 else {
134 double offset_val = double(RNA_float_get(op->ptr, "offset"));
135 BKE_unit_value_as_string(offset_str,
137 offset_val * sce->unit.scale_length,
138 3,
140 &sce->unit,
141 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"),
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
180 WorkspaceStatus status(C);
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(
192 IFACE_("Profile"), op->type, BEV_MODAL_VALUE_PROFILE, opdata->value_mode == PROFILE_VALUE);
193
194 status.opmodal(IFACE_("Clamp"),
195 op->type,
197 RNA_boolean_get(op->ptr, "clamp_overlap"));
198 status.opmodal(IFACE_("Harden"),
199 op->type,
201 RNA_boolean_get(op->ptr, "harden_normals"));
202 status.opmodal(
203 IFACE_("Seam"), op->type, BEV_MODAL_MARK_SEAM_TOGGLE, RNA_boolean_get(op->ptr, "mark_seam"));
204 status.opmodal(IFACE_("Sharp"),
205 op->type,
207 RNA_boolean_get(op->ptr, "mark_sharp"));
208
209 std::string desc;
210
211 desc = fmt::format("{} ({}) ", IFACE_("Affect"), affect_str);
212 status.opmodal(desc.c_str(), op->type, BEV_MODAL_AFFECT_CHANGE);
213
214 desc = fmt::format("{} ({}) ", IFACE_("Outer"), omiter_str);
215 status.opmodal(desc.c_str(), op->type, BEV_MODAL_OUTER_MITER_CHANGE);
216
217 desc = fmt::format("{} ({}) ", IFACE_("Inner"), imiter_str);
218 status.opmodal(desc.c_str(), op->type, BEV_MODAL_INNER_MITER_CHANGE);
219
220 desc = fmt::format("{} ({}) ", IFACE_("Profile Type"), profile_type_str);
221 status.opmodal(desc.c_str(), op->type, BEV_MODAL_PROFILE_TYPE_CHANGE);
222
223 desc = fmt::format("{} ({}) ", IFACE_("Intersection"), vmesh_str);
224 status.opmodal(desc.c_str(), op->type, BEV_MODAL_VERTEX_MESH_CHANGE);
225}
226
227static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
228{
229 Scene *scene = CTX_data_scene(C);
230 View3D *v3d = CTX_wm_view3d(C);
232 ViewLayer *view_layer = CTX_data_view_layer(C);
233
234 if (is_modal) {
235 RNA_float_set(op->ptr, "offset", 0.0f);
236 RNA_float_set(op->ptr, "offset_pct", 0.0f);
237 }
238
239 op->customdata = MEM_new<BevelData>(__func__);
240 BevelData *opdata = static_cast<BevelData *>(op->customdata);
241 opdata->max_obj_scale = FLT_MIN;
242
243 /* Put the Curve Profile from the toolsettings into the opdata struct */
245
246 {
248 scene, view_layer, v3d);
249 for (Object *obedit : objects) {
250 float scale = mat4_to_scale(obedit->object_to_world().ptr());
251 opdata->max_obj_scale = max_ff(opdata->max_obj_scale, scale);
253 if (em->bm->totvertsel > 0) {
254 opdata->ob_store.append(BevelObjectStore{obedit, {}});
255 }
256 }
257 }
258
259 opdata->is_modal = is_modal;
260 int otype = RNA_enum_get(op->ptr, "offset_type");
262 opdata->segments = float(RNA_int_get(op->ptr, "segments"));
263 float pixels_per_inch = U.dpi;
264
265 for (int i = 0; i < NUM_VALUE_KINDS; i++) {
266 opdata->shift_value[i] = -1.0f;
267 opdata->initial_length[i] = -1.0f;
268 /* NOTE: scale for #OFFSET_VALUE will get overwritten in #edbm_bevel_invoke. */
269 opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
270
271 initNumInput(&opdata->num_input[i]);
272 opdata->num_input[i].idx_max = 0;
273 opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
274 opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
275 if (i == SEGMENTS_VALUE) {
277 }
278 if (i == OFFSET_VALUE) {
279 opdata->num_input[i].unit_sys = scene->unit.system;
280 opdata->num_input[i].unit_type[0] = B_UNIT_LENGTH;
281 }
282 }
283
284 /* avoid the cost of allocating a bm copy */
285 if (is_modal) {
286 ARegion *region = CTX_wm_region(C);
287
288 for (BevelObjectStore &ob_store : opdata->ob_store) {
289 Object *obedit = ob_store.ob;
291 ob_store.mesh_backup = EDBM_redo_state_store(em);
292 }
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 }
373
374 /* no need to de-select existing geometry */
375 if (!EDBM_op_finish(em, &bmop, op, true)) {
376 continue;
377 }
378
380 params.calc_looptris = true;
381 params.calc_normals = true;
382 params.is_destructive = true;
383 EDBM_update(static_cast<Mesh *>(obedit->data), &params);
384 changed = true;
385 }
386 return changed;
387}
388
390{
391 BevelData *opdata = static_cast<BevelData *>(op->customdata);
392 ScrArea *area = CTX_wm_area(C);
393
394 if (area) {
395 ED_area_status_text(area, nullptr);
396 }
397
398 for (BevelObjectStore &ob_store : opdata->ob_store) {
399 BMEditMesh *em = BKE_editmesh_from_object(ob_store.ob);
400 /* Without this, faces surrounded by selected edges/verts will be unselected. */
401 if ((em->selectmode & SCE_SELECT_FACE) == 0) {
403 }
404 }
405
406 if (opdata->is_modal) {
407 ARegion *region = CTX_wm_region(C);
408 for (BevelObjectStore &ob_store : opdata->ob_store) {
409 EDBM_redo_state_free(&ob_store.mesh_backup);
410 }
411 ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel);
412 G.moving = 0;
413 }
414 MEM_delete(opdata);
415 op->customdata = nullptr;
416}
417
419{
420 BevelData *opdata = static_cast<BevelData *>(op->customdata);
421 if (opdata->is_modal) {
422 for (BevelObjectStore &ob_store : opdata->ob_store) {
423 Object *obedit = ob_store.ob;
425 EDBM_redo_state_restore_and_free(&ob_store.mesh_backup, em, true);
426
428 params.calc_looptris = false;
429 params.calc_normals = true;
430 params.is_destructive = true;
431 EDBM_update(static_cast<Mesh *>(obedit->data), &params);
432 }
433 }
434
435 edbm_bevel_exit(C, op);
436
437 /* Need to force re-display or we may still view the modified result. */
439}
440
441/* bevel! yay!! */
443{
444 if (!edbm_bevel_init(C, op, false)) {
445 return OPERATOR_CANCELLED;
446 }
447
448 if (!edbm_bevel_calc(op)) {
449 edbm_bevel_cancel(C, op);
450 return OPERATOR_CANCELLED;
451 }
452
453 edbm_bevel_exit(C, op);
454
455 return OPERATOR_FINISHED;
456}
457
458static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed)
459{
460 BevelData *opdata = static_cast<BevelData *>(op->customdata);
461 const float mlen[2] = {
462 opdata->mcenter[0] - event->mval[0],
463 opdata->mcenter[1] - event->mval[1],
464 };
465 float len = len_v2(mlen);
466 int vmode = opdata->value_mode;
467 if (mode_changed || opdata->initial_length[vmode] == -1.0f) {
468 /* If current value is not default start value, adjust len so that
469 * the scaling and offset in edbm_bevel_mouse_set_value will
470 * start at current value */
471 float value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
472 RNA_float_get(op->ptr, value_rna_name[vmode]);
473 float sc = opdata->scale[vmode];
474 float st = value_start[vmode];
475 if (value != value_start[vmode]) {
476 len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc;
477 }
478 }
479 opdata->initial_length[opdata->value_mode] = len;
480}
481
482static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
483{
485
486 if (!edbm_bevel_init(C, op, true)) {
487 return OPERATOR_CANCELLED;
488 }
489
490 BevelData *opdata = static_cast<BevelData *>(op->customdata);
491
493
494 /* initialize mouse values */
495 float center_3d[3];
496 if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter)) {
497 /* in this case the tool will likely do nothing,
498 * ideally this will never happen and should be checked for above */
499 opdata->mcenter[0] = opdata->mcenter[1] = 0;
500 }
501
502 /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */
503 opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
504 /* since we are affecting untransformed object but seeing in transformed space,
505 * compensate for that */
506 opdata->scale[OFFSET_VALUE] /= opdata->max_obj_scale;
507
508 edbm_bevel_calc_initial_length(op, event, false);
509
511
512 if (!edbm_bevel_calc(op)) {
513 edbm_bevel_cancel(C, op);
514 ED_workspace_status_text(C, nullptr);
515 return OPERATOR_CANCELLED;
516 }
517
519
521}
522
523static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
524{
525 BevelData *opdata = static_cast<BevelData *>(op->customdata);
526 int vmode = opdata->value_mode;
527
528 const float mdiff[2] = {
529 opdata->mcenter[0] - event->mval[0],
530 opdata->mcenter[1] - event->mval[1],
531 };
532
533 float value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
534
535 /* Scale according to value mode */
536 value = value_start[vmode] + value * opdata->scale[vmode];
537
538 /* Fake shift-transform... */
539 if (event->modifier & KM_SHIFT) {
540 if (opdata->shift_value[vmode] < 0.0f) {
541 opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ?
542 opdata->segments :
543 RNA_float_get(op->ptr, value_rna_name[vmode]);
544 }
545 value = (value - opdata->shift_value[vmode]) * 0.1f + opdata->shift_value[vmode];
546 }
547 else if (opdata->shift_value[vmode] >= 0.0f) {
548 opdata->shift_value[vmode] = -1.0f;
549 }
550
551 /* Clamp according to value mode, and store value back. */
552 CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
553 if (vmode == SEGMENTS_VALUE) {
554 opdata->segments = value;
555 RNA_int_set(op->ptr, "segments", int(value + 0.5f));
556 }
557 else {
558 RNA_float_set(op->ptr, value_rna_name[vmode], value);
559 }
560}
561
563{
564 BevelData *opdata = static_cast<BevelData *>(op->customdata);
565
566 int vmode = opdata->value_mode;
567 float value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
568 RNA_float_get(op->ptr, value_rna_name[vmode]);
569 applyNumInput(&opdata->num_input[vmode], &value);
570 CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
571 if (vmode == SEGMENTS_VALUE) {
572 opdata->segments = value;
573 RNA_int_set(op->ptr, "segments", int(value));
574 }
575 else {
576 RNA_float_set(op->ptr, value_rna_name[vmode], value);
577 }
578}
579
581{
582 static const EnumPropertyItem modal_items[] = {
583 {BEV_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel bevel"},
584 {BEV_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", "Confirm bevel"},
585 {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Change Offset", "Value changes offset"},
586 {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Change Profile", "Value changes profile"},
587 {BEV_MODAL_VALUE_SEGMENTS, "VALUE_SEGMENTS", 0, "Change Segments", "Value changes segments"},
588 {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase Segments", "Increase segments"},
589 {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease Segments", "Decrease segments"},
591 "OFFSET_MODE_CHANGE",
592 0,
593 "Change Offset Mode",
594 "Cycle through offset modes"},
596 "CLAMP_OVERLAP_TOGGLE",
597 0,
598 "Toggle Clamp Overlap",
599 "Toggle clamp overlap flag"},
601 "AFFECT_CHANGE",
602 0,
603 "Change Affect Type",
604 "Change which geometry type the operation affects, edges or vertices"},
606 "HARDEN_NORMALS_TOGGLE",
607 0,
608 "Toggle Harden Normals",
609 "Toggle harden normals flag"},
611 "MARK_SEAM_TOGGLE",
612 0,
613 "Toggle Mark Seam",
614 "Toggle mark seam flag"},
616 "MARK_SHARP_TOGGLE",
617 0,
618 "Toggle Mark Sharp",
619 "Toggle mark sharp flag"},
621 "OUTER_MITER_CHANGE",
622 0,
623 "Change Outer Miter",
624 "Cycle through outer miter kinds"},
626 "INNER_MITER_CHANGE",
627 0,
628 "Change Inner Miter",
629 "Cycle through inner miter kinds"},
630 {BEV_MODAL_PROFILE_TYPE_CHANGE, "PROFILE_TYPE_CHANGE", 0, "Cycle through profile types", ""},
632 "VERTEX_MESH_CHANGE",
633 0,
634 "Change Intersection Method",
635 "Cycle through intersection methods"},
636 {0, nullptr, 0, nullptr, nullptr},
637 };
638
639 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Bevel Modal Map");
640
641 /* This function is called for each space-type, only needs to add map once. */
642 if (keymap && keymap->modal_items) {
643 return nullptr;
644 }
645
646 keymap = WM_modalkeymap_ensure(keyconf, "Bevel Modal Map", modal_items);
647
648 WM_modalkeymap_assign(keymap, "MESH_OT_bevel");
649
650 return keymap;
651}
652
653static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
654{
655 BevelData *opdata = static_cast<BevelData *>(op->customdata);
656 const bool has_numinput = hasNumInput(&opdata->num_input[opdata->value_mode]);
657 bool handled = false;
658 short etype = event->type;
659 short eval = event->val;
660
661 /* When activated from toolbar, need to convert left-mouse release to confirm. */
662 if (ELEM(etype, LEFTMOUSE, opdata->launch_event) && (eval == KM_RELEASE) &&
663 RNA_boolean_get(op->ptr, "release_confirm"))
664 {
665 etype = EVT_MODAL_MAP;
666 eval = BEV_MODAL_CONFIRM;
667 }
668 /* Modal numinput active, try to handle numeric inputs first... */
669 if (etype != EVT_MODAL_MAP && eval == KM_PRESS && has_numinput &&
670 handleNumInput(C, &opdata->num_input[opdata->value_mode], event))
671 {
673 edbm_bevel_calc(op);
676 }
677 if (etype == MOUSEMOVE) {
678 if (!has_numinput) {
680 edbm_bevel_calc(op);
682 handled = true;
683 }
684 }
685 else if (etype == MOUSEPAN) {
686 float delta = 0.02f * (event->xy[1] - event->prev_xy[1]);
687 if (opdata->segments >= 1 && opdata->segments + delta < 1) {
688 opdata->segments = 1;
689 }
690 else {
691 opdata->segments += delta;
692 }
693 RNA_int_set(op->ptr, "segments", int(opdata->segments));
694 edbm_bevel_calc(op);
696 handled = true;
697 }
698 else if (etype == EVT_MODAL_MAP) {
699 switch (eval) {
700 case BEV_MODAL_CANCEL:
701 edbm_bevel_cancel(C, op);
702 ED_workspace_status_text(C, nullptr);
703 return OPERATOR_CANCELLED;
704
706 edbm_bevel_calc(op);
707 edbm_bevel_exit(C, op);
708 ED_workspace_status_text(C, nullptr);
709 return OPERATOR_FINISHED;
710
712 opdata->segments = opdata->segments + 1;
713 RNA_int_set(op->ptr, "segments", int(opdata->segments));
714 edbm_bevel_calc(op);
716 handled = true;
717 break;
718
720 opdata->segments = max_ff(opdata->segments - 1, 1);
721 RNA_int_set(op->ptr, "segments", int(opdata->segments));
722 edbm_bevel_calc(op);
724 handled = true;
725 break;
726
728 int type = RNA_enum_get(op->ptr, "offset_type");
729 type++;
730 if (type > BEVEL_AMT_PERCENT) {
731 type = BEVEL_AMT_OFFSET;
732 }
733 if (opdata->value_mode == OFFSET_VALUE && type == BEVEL_AMT_PERCENT) {
735 }
736 else if (opdata->value_mode == OFFSET_VALUE_PERCENT && type != BEVEL_AMT_PERCENT) {
737 opdata->value_mode = OFFSET_VALUE;
738 }
739 RNA_enum_set(op->ptr, "offset_type", type);
740 if (opdata->initial_length[opdata->value_mode] == -1.0f) {
741 edbm_bevel_calc_initial_length(op, event, true);
742 }
743 }
744 /* Update offset accordingly to new offset_type. */
745 if (!has_numinput && ELEM(opdata->value_mode, OFFSET_VALUE, OFFSET_VALUE_PERCENT)) {
747 }
748 edbm_bevel_calc(op);
750 handled = true;
751 break;
752
754 bool clamp_overlap = RNA_boolean_get(op->ptr, "clamp_overlap");
755 RNA_boolean_set(op->ptr, "clamp_overlap", !clamp_overlap);
756 edbm_bevel_calc(op);
758 handled = true;
759 break;
760 }
761
763 opdata->value_mode = OFFSET_VALUE;
764 edbm_bevel_calc_initial_length(op, event, true);
765 break;
766
768 opdata->value_mode = PROFILE_VALUE;
769 edbm_bevel_calc_initial_length(op, event, true);
770 break;
771
773 opdata->value_mode = SEGMENTS_VALUE;
774 edbm_bevel_calc_initial_length(op, event, true);
775 break;
776
778 int affect_type = RNA_enum_get(op->ptr, "affect");
779 affect_type++;
780 if (affect_type > BEVEL_AFFECT_EDGES) {
781 affect_type = BEVEL_AFFECT_VERTICES;
782 }
783 RNA_enum_set(op->ptr, "affect", affect_type);
784 edbm_bevel_calc(op);
786 handled = true;
787 break;
788 }
789
791 bool mark_seam = RNA_boolean_get(op->ptr, "mark_seam");
792 RNA_boolean_set(op->ptr, "mark_seam", !mark_seam);
793 edbm_bevel_calc(op);
795 handled = true;
796 break;
797 }
798
800 bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
801 RNA_boolean_set(op->ptr, "mark_sharp", !mark_sharp);
802 edbm_bevel_calc(op);
804 handled = true;
805 break;
806 }
807
809 int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
810 miter_inner++;
811 if (miter_inner == BEVEL_MITER_PATCH) {
812 miter_inner++; /* no patch option for inner miter */
813 }
814 if (miter_inner > BEVEL_MITER_ARC) {
815 miter_inner = BEVEL_MITER_SHARP;
816 }
817 RNA_enum_set(op->ptr, "miter_inner", miter_inner);
818 edbm_bevel_calc(op);
820 handled = true;
821 break;
822 }
823
825 int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
826 miter_outer++;
827 if (miter_outer > BEVEL_MITER_ARC) {
828 miter_outer = BEVEL_MITER_SHARP;
829 }
830 RNA_enum_set(op->ptr, "miter_outer", miter_outer);
831 edbm_bevel_calc(op);
833 handled = true;
834 break;
835 }
836
838 bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals");
839 RNA_boolean_set(op->ptr, "harden_normals", !harden_normals);
840 edbm_bevel_calc(op);
842 handled = true;
843 break;
844 }
845
847 int profile_type = RNA_enum_get(op->ptr, "profile_type");
848 profile_type++;
849 if (profile_type > BEVEL_PROFILE_CUSTOM) {
850 profile_type = BEVEL_PROFILE_SUPERELLIPSE;
851 }
852 RNA_enum_set(op->ptr, "profile_type", profile_type);
853 edbm_bevel_calc(op);
855 handled = true;
856 break;
857 }
858
860 int vmesh_method = RNA_enum_get(op->ptr, "vmesh_method");
861 vmesh_method++;
862 if (vmesh_method > BEVEL_VMESH_CUTOFF) {
863 vmesh_method = BEVEL_VMESH_ADJ;
864 }
865 RNA_enum_set(op->ptr, "vmesh_method", vmesh_method);
866 edbm_bevel_calc(op);
868 handled = true;
869 break;
870 }
871 }
872 }
873
874 /* Modal numinput inactive, try to handle numeric inputs last... */
875 if (!handled && eval == KM_PRESS &&
876 handleNumInput(C, &opdata->num_input[opdata->value_mode], event))
877 {
879 edbm_bevel_calc(op);
882 }
883
885}
886
888{
889 uiLayout *layout = op->layout;
890 uiLayout *col, *row;
891
892 int profile_type = RNA_enum_get(op->ptr, "profile_type");
893 int offset_type = RNA_enum_get(op->ptr, "offset_type");
894 bool affect_type = RNA_enum_get(op->ptr, "affect");
895
896 uiLayoutSetPropSep(layout, true);
897 uiLayoutSetPropDecorate(layout, false);
898
899 row = uiLayoutRow(layout, false);
900 uiItemR(row, op->ptr, "affect", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
901
902 uiItemS(layout);
903
904 uiItemR(layout, op->ptr, "offset_type", UI_ITEM_NONE, nullptr, ICON_NONE);
905
906 if (offset_type == BEVEL_AMT_PERCENT) {
907 uiItemR(layout, op->ptr, "offset_pct", UI_ITEM_NONE, nullptr, ICON_NONE);
908 }
909 else {
910 uiItemR(layout, op->ptr, "offset", UI_ITEM_NONE, nullptr, ICON_NONE);
911 }
912
913 uiItemR(layout, op->ptr, "segments", UI_ITEM_NONE, nullptr, ICON_NONE);
915 uiItemR(layout,
916 op->ptr,
917 "profile",
919 (profile_type == BEVEL_PROFILE_SUPERELLIPSE) ? IFACE_("Shape") : IFACE_("Miter Shape"),
920 ICON_NONE);
921 }
922 uiItemR(layout, op->ptr, "material", UI_ITEM_NONE, nullptr, ICON_NONE);
923
924 col = uiLayoutColumn(layout, true);
925 uiItemR(col, op->ptr, "harden_normals", UI_ITEM_NONE, nullptr, ICON_NONE);
926 uiItemR(col, op->ptr, "clamp_overlap", UI_ITEM_NONE, nullptr, ICON_NONE);
927 uiItemR(col, op->ptr, "loop_slide", UI_ITEM_NONE, nullptr, ICON_NONE);
928
929 col = uiLayoutColumnWithHeading(layout, true, IFACE_("Mark"));
931 uiItemR(col, op->ptr, "mark_seam", UI_ITEM_NONE, IFACE_("Seams"), ICON_NONE);
932 uiItemR(col, op->ptr, "mark_sharp", UI_ITEM_NONE, IFACE_("Sharp"), ICON_NONE);
933
934 uiItemS(layout);
935
936 col = uiLayoutColumn(layout, false);
938 uiItemR(col, op->ptr, "miter_outer", UI_ITEM_NONE, IFACE_("Miter Outer"), ICON_NONE);
939 uiItemR(col, op->ptr, "miter_inner", UI_ITEM_NONE, IFACE_("Inner"), ICON_NONE);
940 if (RNA_enum_get(op->ptr, "miter_inner") == BEVEL_MITER_ARC) {
941 uiItemR(col, op->ptr, "spread", UI_ITEM_NONE, nullptr, ICON_NONE);
942 }
943
944 uiItemS(layout);
945
946 col = uiLayoutColumn(layout, false);
948 uiItemR(col, op->ptr, "vmesh_method", UI_ITEM_NONE, IFACE_("Intersection Type"), ICON_NONE);
949
950 uiItemR(layout, op->ptr, "face_strength_mode", UI_ITEM_NONE, IFACE_("Face Strength"), ICON_NONE);
951
952 uiItemS(layout);
953
954 row = uiLayoutRow(layout, false);
955 uiItemR(row, op->ptr, "profile_type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
956 if (profile_type == BEVEL_PROFILE_CUSTOM) {
957 /* Get an RNA pointer to ToolSettings to give to the curve profile template code. */
958 Scene *scene = CTX_data_scene(C);
959 PointerRNA toolsettings_ptr = RNA_pointer_create(
960 &scene->id, &RNA_ToolSettings, scene->toolsettings);
961 uiTemplateCurveProfile(layout, &toolsettings_ptr, "custom_bevel_profile_preset");
962 }
963}
964
966{
967 PropertyRNA *prop;
968
969 static const EnumPropertyItem offset_type_items[] = {
970 {BEVEL_AMT_OFFSET, "OFFSET", 0, "Offset", "Amount is offset of new edges from original"},
971 {BEVEL_AMT_WIDTH, "WIDTH", 0, "Width", "Amount is width of new face"},
973 "DEPTH",
974 0,
975 "Depth",
976 "Amount is perpendicular distance from original edge to bevel face"},
977 {BEVEL_AMT_PERCENT, "PERCENT", 0, "Percent", "Amount is percent of adjacent edge length"},
979 "ABSOLUTE",
980 0,
981 "Absolute",
982 "Amount is absolute distance along adjacent edge"},
983 {0, nullptr, 0, nullptr, nullptr},
984 };
985
986 static const EnumPropertyItem prop_profile_type_items[] = {
988 "SUPERELLIPSE",
989 0,
990 "Superellipse",
991 "The profile can be a concave or convex curve"},
993 "CUSTOM",
994 0,
995 "Custom",
996 "The profile can be any arbitrary path between its endpoints"},
997 {0, nullptr, 0, nullptr, nullptr},
998 };
999
1000 static const EnumPropertyItem face_strength_mode_items[] = {
1001 {BEVEL_FACE_STRENGTH_NONE, "NONE", 0, "None", "Do not set face strength"},
1002 {BEVEL_FACE_STRENGTH_NEW, "NEW", 0, "New", "Set face strength on new faces only"},
1004 "AFFECTED",
1005 0,
1006 "Affected",
1007 "Set face strength on new and modified faces only"},
1008 {BEVEL_FACE_STRENGTH_ALL, "ALL", 0, "All", "Set face strength on all faces"},
1009 {0, nullptr, 0, nullptr, nullptr},
1010 };
1011
1012 static const EnumPropertyItem miter_outer_items[] = {
1013 {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Outside of miter is sharp"},
1014 {BEVEL_MITER_PATCH, "PATCH", 0, "Patch", "Outside of miter is squared-off patch"},
1015 {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Outside of miter is arc"},
1016 {0, nullptr, 0, nullptr, nullptr},
1017 };
1018
1019 static const EnumPropertyItem miter_inner_items[] = {
1020 {BEVEL_MITER_SHARP, "SHARP", 0, "Sharp", "Inside of miter is sharp"},
1021 {BEVEL_MITER_ARC, "ARC", 0, "Arc", "Inside of miter is arc"},
1022 {0, nullptr, 0, nullptr, nullptr},
1023 };
1024
1025 static EnumPropertyItem vmesh_method_items[] = {
1026 {BEVEL_VMESH_ADJ, "ADJ", 0, "Grid Fill", "Default patterned fill"},
1028 "CUTOFF",
1029 0,
1030 "Cutoff",
1031 "A cutoff at each profile's end before the intersection"},
1032 {0, nullptr, 0, nullptr, nullptr},
1033 };
1034
1035 static const EnumPropertyItem prop_affect_items[] = {
1036 {BEVEL_AFFECT_VERTICES, "VERTICES", 0, "Vertices", "Affect only vertices"},
1037 {BEVEL_AFFECT_EDGES, "EDGES", 0, "Edges", "Affect only edges"},
1038 {0, nullptr, 0, nullptr, nullptr},
1039 };
1040
1041 /* identifiers */
1042 ot->name = "Bevel";
1043 ot->description = "Cut into selected items at an angle to create bevel or chamfer";
1044 ot->idname = "MESH_OT_bevel";
1045
1046 /* api callbacks */
1052 ot->ui = edbm_bevel_ui;
1053
1054 /* flags */
1056
1057 /* properties */
1059 "offset_type",
1060 offset_type_items,
1061 0,
1062 "Width Type",
1063 "The method for determining the size of the bevel");
1064 prop = RNA_def_property(ot->srna, "offset", PROP_FLOAT, PROP_DISTANCE);
1065 RNA_def_property_range(prop, 0.0, 1e6);
1066 RNA_def_property_ui_range(prop, 0.0, 100.0, 1, 3);
1067 RNA_def_property_ui_text(prop, "Width", "Bevel amount");
1068
1070 "profile_type",
1071 prop_profile_type_items,
1072 0,
1073 "Profile Type",
1074 "The type of shape used to rebuild a beveled section");
1075
1076 prop = RNA_def_property(ot->srna, "offset_pct", PROP_FLOAT, PROP_PERCENTAGE);
1077 RNA_def_property_range(prop, 0.0, 100);
1078 RNA_def_property_ui_text(prop, "Width Percent", "Bevel amount for percentage method");
1079
1081 "segments",
1082 1,
1083 1,
1085 "Segments",
1086 "Segments for curved edge",
1087 1,
1088 100);
1089
1091 "profile",
1092 0.5f,
1094 1.0f,
1095 "Profile",
1096 "Controls profile shape (0.5 = round)",
1098 1.0f);
1099
1101 "affect",
1102 prop_affect_items,
1104 "Affect",
1105 "Affect edges or vertices");
1106
1108 "clamp_overlap",
1109 false,
1110 "Clamp Overlap",
1111 "Do not allow beveled edges/vertices to overlap each other");
1112
1114 ot->srna, "loop_slide", true, "Loop Slide", "Prefer sliding along edges to even widths");
1115
1116 RNA_def_boolean(ot->srna, "mark_seam", false, "Mark Seams", "Mark Seams along beveled edges");
1117
1118 RNA_def_boolean(ot->srna, "mark_sharp", false, "Mark Sharp", "Mark beveled edges as sharp");
1119
1121 "material",
1122 -1,
1123 -1,
1124 INT_MAX,
1125 "Material Index",
1126 "Material for bevel faces (-1 means use adjacent faces)",
1127 -1,
1128 100);
1129
1131 "harden_normals",
1132 false,
1133 "Harden Normals",
1134 "Match normals of new faces to adjacent faces");
1135
1137 "face_strength_mode",
1138 face_strength_mode_items,
1140 "Face Strength Mode",
1141 "Whether to set face strength, and which faces to set face strength on");
1142
1144 "miter_outer",
1145 miter_outer_items,
1147 "Outer Miter",
1148 "Pattern to use for outside of miters");
1149
1151 "miter_inner",
1152 miter_inner_items,
1154 "Inner Miter",
1155 "Pattern to use for inside of miters");
1156
1158 "spread",
1159 0.1f,
1160 0.0f,
1161 1e6f,
1162 "Spread",
1163 "Amount to spread arcs for arc inner miters",
1164 0.0f,
1165 100.0f);
1166
1168 "vmesh_method",
1169 vmesh_method_items,
1171 "Vertex Mesh Method",
1172 "The method to use to create meshes at intersections");
1173
1174 prop = RNA_def_boolean(ot->srna, "release_confirm", false, "Confirm on Release", "");
1176}
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:63
@ 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:107
@ B_UNIT_NONE
Definition BKE_unit.hh:106
size_t BKE_unit_value_as_string(char *str, int str_maxncpy, double value, int prec, int type, const UnitSettings *settings, bool pad)
Definition unit.cc:1876
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:597
#define CLAMP(a, b, c)
#define ELEM(...)
#define IFACE_(msgid)
typedef double(DMatrix)[4][4]
Object is a sort of wrapper for general info.
@ SCE_SELECT_FACE
@ V3D_AROUND_CENTER_MEDIAN
@ 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: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:803
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:966
bool ED_operator_editmesh(bContext *C)
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
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
bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2])
void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_info)
Definition ed_draw.cc:626
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
Read Guarded memory(de)allocation.
@ PROP_FLOAT
Definition RNA_types.hh:67
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
@ PROP_DISTANCE
Definition RNA_types.hh:159
@ PROP_PERCENTAGE
Definition RNA_types.hh:153
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
#define UI_ITEM_NONE
uiLayout * uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiTemplateCurveProfile(uiLayout *layout, PointerRNA *ptr, const char *propname)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
@ OPTYPE_BLOCKING
Definition WM_types.hh:164
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_GRAB_CURSOR_XY
Definition WM_types.hh:168
@ OPTYPE_REGISTER
Definition WM_types.hh:160
@ KM_PRESS
Definition WM_types.hh:284
@ KM_RELEASE
Definition WM_types.hh:285
@ KM_SHIFT
Definition WM_types.hh:255
@ BM_ELEM_SELECT
#define BM_FACE
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_VMESH_ADJ
@ BEVEL_VMESH_CUTOFF
@ BEVEL_AMT_WIDTH
@ BEVEL_AMT_ABSOLUTE
@ BEVEL_AMT_PERCENT
@ BEVEL_AMT_OFFSET
@ BEVEL_AMT_DEPTH
@ BEVEL_MITER_PATCH
@ BEVEL_MITER_SHARP
@ BEVEL_MITER_ARC
@ BEVEL_PROFILE_SUPERELLIPSE
@ BEVEL_PROFILE_CUSTOM
@ BEVEL_FACE_STRENGTH_NONE
@ BEVEL_FACE_STRENGTH_AFFECTED
@ BEVEL_FACE_STRENGTH_NEW
@ BEVEL_FACE_STRENGTH_ALL
@ BEVEL_AFFECT_VERTICES
@ BEVEL_AFFECT_EDGES
unsigned int U
Definition btGjkEpa3.h:78
void opmodal(std::string text, const wmOperatorType *ot, int propvalue, bool inverted=false)
Definition area.cc:934
int len
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 int edbm_bevel_exec(bContext *C, wmOperator *op)
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 int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void edbm_bevel_numinput_set_value(wmOperator *op)
void MESH_OT_bevel(wmOperatorType *ot)
static const char * value_rna_name[NUM_VALUE_KINDS]
#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
@ 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 int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#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)
draw_view in_light_buf[] float
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define G(x, y, z)
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(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)
short selectmode
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
int totvertsel
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 UnitSettings unit
struct CurveProfile * custom_bevel_profile_preset
uint8_t modifier
Definition WM_types.hh:739
short type
Definition WM_types.hh:722
const void * modal_items
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
StructRNA * srna
Definition WM_types.hh:1080
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
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:4125
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:933
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:960