10#include <fmt/format.h>
58#include "RNA_prototypes.hh"
81#define USE_FACE_CREATE_SEL_EXTEND
106 for (
Object *obedit : objects) {
129 params.calc_looptris =
true;
130 params.calc_normals =
false;
131 params.is_destructive =
true;
144 {0,
nullptr, 0,
nullptr,
nullptr},
164 prop =
RNA_def_int(
ot->
srna,
"number_cuts", 1, 1, 100,
"Number of Cuts",
"", 1, 10);
170 ot->
srna,
"smoothness", 0.0f, 0.0f, 1e3f,
"Smoothness",
"Smoothness factor", 0.0f, 1.0f);
178 "When disabled, newly created faces are limited to 3 and 4 sided faces");
185 "How to subdivide quad corners (anything other than Straight Cut will prevent n-gons)");
193 "Fractal randomness factor",
197 "fractal_along_normal",
202 "Apply fractal displacement along normal only",
211 "Seed for the random number generator",
236 const int cuts_default)
243 {0,
nullptr, 0,
nullptr,
nullptr},
249 ot->
srna,
"number_cuts", cuts_default, 0, 1000,
"Number of Cuts",
"", cuts_min, 64);
254 prop_subd_edgering_types,
257 "Interpolation method");
260 ot->
srna,
"smoothness", 1.0f, 0.0f, 1e3f,
"Smoothness",
"Smoothness factor", 0.0f, 2.0f);
264 "profile_shape_factor",
269 "How much intermediary new edges are shrunk/expanded",
301 for (
Object *obedit : objects) {
310 "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f "
311 "profile_shape=%i profile_shape_factor=%f",
323 params.calc_looptris =
true;
324 params.calc_normals =
false;
325 params.is_destructive =
true;
335 ot->
name =
"Subdivide Edge-Ring";
336 ot->
description =
"Subdivide perpendicular edges to the selected edge-ring";
337 ot->
idname =
"MESH_OT_subdivide_edgering";
363 for (
Object *obedit : objects) {
385 params.calc_looptris =
true;
386 params.calc_normals =
false;
387 params.is_destructive =
true;
397 ot->
name =
"Un-Subdivide";
410 ot->
srna,
"iterations", 2, 1, 1000,
"Iterations",
"Number of times to un-subdivide", 1, 100);
429 const int totelem_old[3],
430 const int totelem_new[3])
434 "Removed: %d vertices, %d edges, %d faces",
435 totelem_old[0] - totelem_new[0],
436 totelem_old[1] - totelem_new[1],
437 totelem_old[2] - totelem_new[2]);
447 bool changed_multi =
false;
449 for (
Object *obedit : objects) {
505 changed_multi =
true;
512 params.calc_looptris =
true;
513 params.calc_normals =
false;
514 params.is_destructive =
true;
532 {0,
nullptr, 0,
nullptr,
nullptr},
537 ot->
description =
"Delete selected vertices, edges or faces";
552 prop_mesh_delete_types,
555 "Method used for deleting mesh data");
574 }
while ((l_iter = l_iter->
next) != l_first);
583 int totelem_old_sel[3];
595 for (
Object *obedit : objects) {
642 params.calc_looptris =
true;
643 params.calc_normals =
false;
644 params.is_destructive =
true;
659 ot->
name =
"Delete Loose";
661 ot->
idname =
"MESH_OT_delete_loose";
689 for (
Object *obedit : objects) {
701 params.calc_looptris =
true;
702 params.calc_normals =
false;
703 params.is_destructive =
true;
713 ot->
name =
"Collapse Edges & Faces";
715 "Collapse isolated edge and face regions, merging data such as UVs and color attributes. "
716 "This can collapse edge-rings as well as regions of connected faces into vertices";
717 ot->
idname =
"MESH_OT_edge_collapse";
738 uint vote_on_smooth[2] = {0, 0};
746 return (vote_on_smooth[0] < vote_on_smooth[1]);
749#ifdef USE_FACE_CREATE_SEL_EXTEND
762 if ((e_used ==
nullptr) || (e_used != e_iter)) {
765 if (i >= e_arr_len) {
916 bool changed_multi =
false;
921 for (
Object *obedit : objects) {
933#ifdef USE_FACE_CREATE_SEL_EXTEND
944 "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
959#ifdef USE_FACE_CREATE_SEL_EXTEND
963 (ele_desel_face =
static_cast<BMFace *
>(
993 params.calc_looptris =
true;
994 params.calc_normals =
false;
995 params.is_destructive =
true;
997 changed_multi =
true;
1000 if (!changed_multi) {
1010 ot->
name =
"Make Edge/Face";
1012 ot->
idname =
"MESH_OT_edge_face_add";
1038 for (
Object *obedit : objects) {
1067 for (
Object *obedit : objects) {
1069 params.calc_looptris =
true;
1070 params.calc_normals =
false;
1071 params.is_destructive =
false;
1117 for (
Object *obedit : objects) {
1141 params.calc_looptris =
true;
1142 params.calc_normals =
false;
1143 params.is_destructive =
false;
1173 "Consider vertices instead of edges to select which edges to (un)tag as sharp");
1188 bool is_pair = (verts_len == 2);
1190 bool check_degenerate =
true;
1192 bool checks_succeded =
true;
1195 if (verts_len < 2) {
1214 check_degenerate =
false;
1223 "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
1229 checks_succeded =
false;
1236 "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
1242 checks_succeded =
false;
1245 if (checks_succeded) {
1254 if (
len && is_pair) {
1260 bool em_backup_free =
true;
1267 em_backup_free =
false;
1276 params.calc_looptris =
true;
1277 params.calc_normals =
false;
1278 params.is_destructive =
true;
1282 if (em_backup_free) {
1295 uint failed_objects_len = 0;
1299 for (
Object *obedit : objects) {
1303 failed_objects_len++;
1312 ot->
name =
"Vertex Connect";
1313 ot->
idname =
"MESH_OT_vert_connect";
1314 ot->
description =
"Connect selected vertices of faces, splitting the face";
1382 bool changed =
false;
1383 bool has_wire =
false;
1399 if (has_wire ==
false) {
1404 ese = ese_last->
next;
1414 }
while ((
void)(ese_last = ese), (ese = ese->
next));
1421 if (changed ==
false) {
1439 ese = ese_prev->
next;
1452 }
while ((
void)(ese_prev = ese), (ese = ese->
next));
1454 if (changed ==
false) {
1479 ListBase selected_orig = {
nullptr,
nullptr};
1502 BMEdge *e_prev = ese->prev ? (
BMEdge *)ese->prev->ele :
nullptr;
1510 if ((e_curr->
v1 != l_curr->
v) == (e_prev->
v1 != l_prev->
v)) {
1519 v = (&e_curr->
v1)[side];
1524 v = (&e_curr->
v1)[!side];
1542 uint failed_selection_order_len = 0;
1543 uint failed_connect_len = 0;
1547 for (
Object *obedit : objects) {
1551 ListBase selected_orig = {
nullptr,
nullptr};
1560 failed_connect_len++;
1582 params.calc_looptris =
true;
1583 params.calc_normals =
false;
1584 params.is_destructive =
true;
1588 failed_selection_order_len++;
1597 if (failed_selection_order_len == objects.size()) {
1601 if (failed_connect_len == objects.size()) {
1612 ot->
name =
"Vertex Connect Path";
1613 ot->
idname =
"MESH_OT_vert_connect_path";
1614 ot->
description =
"Connect vertices by their selection order, creating edges, splitting faces";
1636 for (
Object *obedit : objects) {
1644 em, op,
"faces.out",
true,
"connect_verts_concave faces=%hf",
BM_ELEM_SELECT))
1649 params.calc_looptris =
true;
1650 params.calc_normals =
false;
1651 params.is_destructive =
true;
1661 ot->
name =
"Split Concave Faces";
1662 ot->
idname =
"MESH_OT_vert_connect_concave";
1687 for (
Object *obedit : objects) {
1698 "connect_verts_nonplanar faces=%hf angle_limit=%f",
1706 params.calc_looptris =
true;
1707 params.calc_normals =
false;
1708 params.is_destructive =
true;
1720 ot->
name =
"Split Non-Planar Faces";
1721 ot->
idname =
"MESH_OT_vert_connect_nonplanar";
1722 ot->
description =
"Split non-planar faces that exceed the angle threshold";
1763 for (
Object *obedit : objects) {
1777 em, op,
"planar_faces faces=%hf iterations=%i factor=%f",
BM_ELEM_SELECT, repeat, fac))
1783 params.calc_looptris =
true;
1784 params.calc_normals =
true;
1785 params.is_destructive =
true;
1795 ot->
name =
"Make Planar Faces";
1796 ot->
idname =
"MESH_OT_face_make_planar";
1827 em, op,
"edges.out",
false,
"split_edges edges=%he",
BM_ELEM_SELECT))
1836 params.calc_looptris =
true;
1837 params.calc_normals =
false;
1838 params.is_destructive =
true;
1861 if (eed->
l !=
nullptr) {
1877 "split_edges edges=%he verts=%hv use_verts=%b",
1886 if (eed->
l !=
nullptr) {
1896 for (
int i = 0; i < 2; i++) {
1911 params.calc_looptris =
true;
1912 params.calc_normals =
false;
1913 params.is_destructive =
true;
1927 for (
Object *obedit : objects) {
1954 ot->
description =
"Split selected edges so that each neighbor face gets its own copy";
1965 {
BM_EDGE,
"EDGE", 0,
"Faces by Edges",
"Split faces along selected edges"},
1969 "Faces & Edges by Vertices",
1970 "Split faces and edges connected to selected vertices"},
1971 {0,
nullptr, 0,
nullptr,
nullptr},
1990 bool changed =
false;
1992 for (
Object *obedit : objects) {
2005 "duplicate geom=%hvef use_select_history=%b use_edge_flip_from_face=%b",
2027 params.calc_looptris =
true;
2028 params.calc_normals =
false;
2029 params.is_destructive =
true;
2049 ot->
description =
"Duplicate selected vertices, edges or faces";
2073 return lnors_ed_arr;
2078 if (!lnors_ed_arr) {
2082 if (lnors_ed_arr->
totloop == 0) {
2099 for (
int i = 0; i < lnors_ed_arr_new_full->
totloop; i++, lnor_ed_new_full++) {
2135 BLI_assert(lnor_ed !=
nullptr && lnor_ed_new !=
nullptr);
2144 }
while (
l != l_start);
2169 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
2177 params.calc_looptris =
true;
2178 params.calc_normals =
false;
2179 params.is_destructive =
false;
2187 params.calc_looptris =
true;
2188 params.calc_normals =
false;
2189 params.is_destructive =
false;
2197 bool has_flipped_faces =
false;
2203 has_flipped_faces =
true;
2208 params.calc_looptris =
true;
2209 params.calc_normals =
false;
2210 params.is_destructive =
false;
2214 if (lnors_ed_arr !=
nullptr) {
2226 for (
Object *obedit : objects) {
2246 for (
Object *obedit : objects) {
2269 ot->
name =
"Flip Normals";
2270 ot->
description =
"Flip the direction of selected faces' normals (and of their vertices)";
2271 ot->
idname =
"MESH_OT_flip_normals";
2283 "Custom Normals Only",
2284 "Only flip the custom loop normals of the selected elements");
2302 int tot_failed_all = 0;
2303 bool no_selected_edges =
true, invalid_selected_edges =
true;
2309 for (
Object *obedit : objects) {
2316 no_selected_edges =
false;
2339 invalid_selected_edges =
false;
2357 const int tot_failed = tot - tot_rotate;
2359 tot_failed_all += tot_failed;
2361 if (tot_failed != 0) {
2375 params.calc_looptris =
true;
2376 params.calc_normals =
false;
2377 params.is_destructive =
true;
2381 if (no_selected_edges) {
2383 op->
reports,
RPT_ERROR,
"Select edges or face pairs for edge loops to rotate about");
2389 if (invalid_selected_edges) {
2394 if (tot_failed_all != 0) {
2404 ot->
name =
"Rotate Selected Edge";
2405 ot->
description =
"Rotate selected edge or adjoining faces";
2406 ot->
idname =
"MESH_OT_edge_rotate";
2430 bool changed =
false;
2434 for (
Object *obedit : objects) {
2463 params.calc_looptris =
true;
2464 params.calc_normals =
false;
2465 params.is_destructive =
false;
2481 ot->
name =
"Hide Selected";
2483 ot->
description =
"Hide (un)selected vertices, edges or faces";
2494 ot->
srna,
"unselected",
false,
"Unselected",
"Hide unselected rather than selected");
2511 for (
Object *obedit : objects) {
2516 params.calc_looptris =
true;
2517 params.calc_normals =
false;
2518 params.is_destructive =
false;
2529 ot->
name =
"Reveal Hidden";
2531 ot->
description =
"Reveal all hidden vertices, edges and faces";
2557 for (
Object *obedit : objects) {
2578 if (lnors_ed_arr !=
nullptr) {
2584 params.calc_looptris =
true;
2585 params.calc_normals =
false;
2586 params.is_destructive =
false;
2596 ot->
name =
"Recalculate Normals";
2597 ot->
description =
"Make face and vertex normals point either outside or inside the mesh";
2598 ot->
idname =
"MESH_OT_normals_make_consistent";
2631 int tot_selected = 0, tot_locked = 0;
2634 for (
Object *obedit : objects) {
2635 Mesh *mesh =
static_cast<Mesh *
>(obedit->data);
2637 bool mirrx =
false, mirry =
false, mirrz =
false;
2638 float clip_dist = 0.0f;
2680 for (
int i = 0; i < repeat; i++) {
2684 "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
2685 "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
2707 params.calc_looptris =
true;
2708 params.calc_normals =
false;
2709 params.is_destructive =
false;
2713 if (tot_selected == 0 && !tot_locked) {
2723 ot->
name =
"Smooth Vertices";
2725 ot->
idname =
"MESH_OT_vertices_smooth";
2735 ot->
srna,
"factor", 0.0f, -10.0f, 10.0f,
"Smoothing",
"Smoothing factor", 0.0f, 1.0f);
2737 ot->
srna,
"repeat", 1, 1, 1000,
"Repeat",
"Number of times to smooth the mesh", 1, 100);
2757 int tot_selected = 0, tot_locked = 0;
2775 for (
Object *obedit : objects) {
2777 Mesh *mesh =
static_cast<Mesh *
>(obedit->data);
2796 bool failed_repeat_loop =
false;
2797 for (
int i = 0; i < repeat; i++) {
2800 "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f "
2801 "use_x=%b use_y=%b use_z=%b preserve_volume=%b",
2810 failed_repeat_loop =
true;
2814 if (failed_repeat_loop) {
2825 params.calc_looptris =
true;
2826 params.calc_normals =
false;
2827 params.is_destructive =
false;
2831 if (tot_selected == 0 && !tot_locked) {
2841 ot->
name =
"Laplacian Smooth Vertices";
2843 ot->
idname =
"MESH_OT_vertices_smooth_laplacian";
2853 ot->
srna,
"repeat", 1, 1, 1000,
"Number of iterations to smooth the mesh",
"", 1, 200);
2855 ot->
srna,
"lambda_factor", 1.0f, 1e-7f, 1000.0f,
"Lambda factor",
"", 1e-7f, 1000.0f);
2861 "Lambda factor in border",
2875 "Apply volume preservation after smooth");
2889 if (em ==
nullptr) {
2906 for (
Object *obedit : objects) {
2915 params.calc_looptris =
false;
2916 params.calc_normals =
false;
2917 params.is_destructive =
false;
2927 ot->
name =
"Shade Smooth";
2928 ot->
description =
"Display faces smooth (using vertex normals)";
2929 ot->
idname =
"MESH_OT_faces_shade_smooth";
2951 for (
Object *obedit : objects) {
2960 params.calc_looptris =
false;
2961 params.calc_normals =
false;
2962 params.is_destructive =
false;
2974 ot->
idname =
"MESH_OT_faces_shade_flat";
2999 for (
Object *obedit : objects) {
3017 params.calc_looptris =
false;
3018 params.calc_normals =
false;
3019 params.is_destructive =
false;
3032 for (
Object *obedit : objects) {
3049 params.calc_looptris =
false;
3050 params.calc_normals =
false;
3051 params.is_destructive =
false;
3068 for (
uint ob_index = 0; ob_index < objects.size(); ob_index++) {
3069 Object *ob = objects[ob_index];
3090 "rotate_colors faces=%hf use_ccw=%b color_index=%i",
3103 params.calc_looptris =
false;
3104 params.calc_normals =
false;
3105 params.is_destructive =
false;
3119 for (
Object *obedit : objects) {
3139 em, &bmop, op,
"reverse_colors faces=%hf color_index=%i",
BM_ELEM_SELECT, color_index);
3148 params.calc_looptris =
false;
3149 params.calc_normals =
false;
3150 params.is_destructive =
false;
3178 ot->
name =
"Reverse UVs";
3179 ot->
idname =
"MESH_OT_uvs_reverse";
3180 ot->
description =
"Flip direction of UV coordinates inside faces";
3196 ot->
name =
"Rotate Colors";
3197 ot->
idname =
"MESH_OT_colors_rotate";
3198 ot->
description =
"Rotate face corner color attribute inside faces";
3214 ot->
name =
"Reverse Colors";
3215 ot->
idname =
"MESH_OT_colors_reverse";
3216 ot->
description =
"Flip direction of face corner color attribute inside faces";
3227 RNA_def_enum(
ot->
srna,
"axis", axis_items, DIRECTION_CW,
"Axis",
"Axis to mirror colors around");
3246 const bool use_first,
3247 const bool use_uvmerge,
3259 if (use_first ==
false) {
3282 em, wmop,
"pointmerge_facedata verts=%hv vert_snap=%e",
BM_ELEM_SELECT, mergevert))
3299 const bool use_cursor,
3300 const bool use_uvmerge,
3305 float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
3306 const float *vco =
nullptr;
3309 vco = scene->cursor.location;
3312 mul_m4_v3(ob->world_to_object().ptr(), co);
3329 fac = 1.0f /
float(i);
3361 for (
Object *obedit : objects) {
3399 params.calc_looptris =
true;
3400 params.calc_normals =
false;
3401 params.is_destructive =
true;
3423 {0,
nullptr, 0,
nullptr,
nullptr},
3516 const bool use_sharp_edge_from_normals =
RNA_boolean_get(op->
ptr,
"use_sharp_edge_from_normals");
3518 int count_multi = 0;
3525 for (
Object *obedit : objects) {
3534 const int totvert_orig = em->
bm->
totvert;
3553 if (use_unselected) {
3561 if (!
EDBM_op_callf(em, op,
"weld_verts targetmap=%S", &bmop,
"targetmap.out")) {
3580 count_multi +=
count;
3582 params.calc_looptris =
true;
3583 params.calc_normals =
false;
3584 params.is_destructive =
true;
3591 count_multi == 1 ?
"Removed %d vertex" :
"Removed %d vertices",
3600 ot->
name =
"Merge by Distance";
3601 ot->
description =
"Merge vertices based on their proximity";
3602 ot->
idname =
"MESH_OT_remove_doubles";
3617 "Maximum distance between elements to merge",
3624 "Merge selected to other unselected vertices");
3627 "use_sharp_edge_from_normals",
3630 "Calculate sharp edges using custom normal data (when available)");
3662 for (
int i = 0; i < totshape; i++) {
3663 co =
static_cast<float *
>(
3675 int tot_shapekeys = 0;
3676 int tot_selected_verts_objects = 0;
3681 for (
Object *obedit : objects) {
3682 Mesh *mesh =
static_cast<Mesh *
>(obedit->data);
3683 BMEditMesh *em = mesh->runtime->edit_mesh.get();
3695 tot_selected_verts_objects++;
3697 const bool use_symmetry = (mesh->symmetry &
ME_SYMMETRY_X) != 0;
3714 params.calc_looptris =
false;
3715 params.calc_normals =
false;
3716 params.is_destructive =
false;
3720 if (tot_selected_verts_objects == 0) {
3726 if (tot_shapekeys == 0) {
3737 ot->
name =
"Shape Propagate";
3738 ot->
description =
"Apply selected vertex locations to all other shape keys";
3739 ot->
idname =
"MESH_OT_shape_propagate_to_all";
3760 Key *key_ref = me_ref->
key;
3768 int totshape_ref = 0;
3777 if (totshape_ref == 0 || shape_ref < 0) {
3781 if (shape_ref >= totshape_ref) {
3791 int tot_selected_verts_objects = 0, tot_locked = 0;
3794 for (
Object *obedit : objects) {
3795 Mesh *mesh =
static_cast<Mesh *
>(obedit->data);
3796 Key *key = mesh->key;
3798 BMEditMesh *em = mesh->runtime->edit_mesh.get();
3810 tot_selected_verts_objects++;
3819 const bool use_symmetry = (mesh->symmetry &
ME_SYMMETRY_X) != 0;
3834 sco =
static_cast<float *
>(
3840 const float *rco =
static_cast<const float *
>(
3858 params.calc_looptris =
true;
3859 params.calc_normals =
true;
3860 params.is_destructive =
false;
3865 if (tot_selected_verts_objects == 0 && !tot_locked) {
3893 tmp.
value = totitem;
3918 uiItemPointerR(layout, op->
ptr,
"shape", &ptr_key,
"key_blocks",
nullptr, ICON_SHAPEKEY_DATA);
3928 ot->
name =
"Blend from Shape";
3930 ot->
idname =
"MESH_OT_blend_from_shape";
3947 RNA_def_float(
ot->
srna,
"blend", 1.0f, -1e3f, 1e3f,
"Blend",
"Blending factor", -2.0f, 2.0f);
3965 for (
Object *obedit : objects) {
3999 params.calc_looptris =
true;
4000 params.calc_normals =
false;
4001 params.is_destructive =
true;
4013 ot->
description =
"Create a solid skin by extruding, compensating for sharp angles";
4024 ot->
srna,
"thickness", 0.01f, -1e4f, 1e4f,
"Thickness",
"", -10.0f, 10.0f);
4070 "duplicate geom=%hvef dest=%p",
4075 "delete geom=%hvef context=%i",
4108 bm_new_allocsize.
totvert = verts_len;
4109 bm_new_allocsize.totedge = edges_len;
4110 bm_new_allocsize.totloop = faces_len * 3;
4111 bm_new_allocsize.totface = faces_len;
4113 const bool use_custom_normals = (bm_old->
lnor_spacearr !=
nullptr);
4120 if (use_custom_normals) {
4146 if (use_custom_normals) {
4150 for (
uint i = 0; i < verts_len; i++) {
4183 ID *obdata =
static_cast<ID *
>(ob->
data);
4188 if ((totcolp && matarar) == 0) {
4198 if (mat_nr < ob->totcol) {
4199 ma_ob = ob->
mat[mat_nr];
4207 if (mat_nr < *totcolp) {
4208 ma_obdata = (*matarar)[mat_nr];
4211 ma_obdata =
nullptr;
4221 (*matarar)[0] = ma_obdata;
4236 bool result =
false;
4240 const short mat_nr = f_cmp->
mat_nr;
4246 if (f->
mat_nr == mat_nr) {
4255 }
while ((l_iter = l_iter->
next) != l_first);
4278 result |= (base_new !=
nullptr);
4290 const bool clear_object_data =
true;
4292 bool result =
false;
4298 int(*groups)[3] =
nullptr;
4300 bm_old, vert_groups.
data(), edge_groups.
data(), face_groups.
data(), &groups);
4301 if (groups_len <= 1) {
4306 if (clear_object_data) {
4313 uint group_ofs[3] = {
uint(groups[0][0]),
uint(groups[0][1]),
uint(groups[0][2])};
4314 for (
int i = 1; i < groups_len; i++) {
4320 vert_groups.
data() + group_ofs[0],
4322 edge_groups.
data() + group_ofs[1],
4324 face_groups.
data() + group_ofs[2],
4326 result |= (base_new !=
nullptr);
4328 group_ofs[0] += groups[i][0];
4329 group_ofs[1] += groups[i][1];
4330 group_ofs[2] += groups[i][2];
4336 if (clear_object_data) {
4352 bool changed_multi =
false;
4355 uint empty_selection_len = 0;
4358 for (
const int base_index : bases.
index_range()) {
4359 Base *base = bases[base_index];
4365 if (++empty_selection_len == bases.
size()) {
4373 bool changed =
false;
4391 params.calc_looptris =
true;
4392 params.calc_normals =
false;
4393 params.is_destructive =
true;
4396 changed_multi |= changed;
4407 Object *ob = base_iter->object;
4423 bool changed =
false;
4447 changed_multi |= changed;
4452 if (changed_multi) {
4470 {0,
nullptr, 0,
nullptr,
nullptr},
4475 ot->
description =
"Separate selected geometry into a new mesh";
4500 bool has_selected_edges =
false, has_faces_filled =
false;
4506 for (
Object *obedit : objects) {
4509 const int totface_orig = em->
bm->
totface;
4514 has_selected_edges =
true;
4518 em, &bmop, op,
"triangle_fill edges=%he use_beauty=%b",
BM_ELEM_SELECT, use_beauty))
4530 has_faces_filled =
true;
4541 params.calc_looptris =
true;
4542 params.calc_normals =
false;
4543 params.is_destructive =
true;
4547 if (!has_selected_edges) {
4552 if (!has_faces_filled) {
4611 const float eps_even = 1e-3f;
4639 for (
int i = 0; i < edges_len; i++) {
4644 span = verts_len / 4;
4647 span =
min_ii(span, (verts_len / 2) - 1);
4649 offset =
mod_i(offset, verts_len);
4651 if ((
count == 1) && ((verts_len & 1) == 0) && (verts_len == edges_len)) {
4659 if (v_act && (v_act_link =
static_cast<LinkData *
>(
4667 float angle_best = -1.0f;
4670 if ((angle > angle_best) || (v_link_best ==
nullptr)) {
4672 v_link_best = v_link;
4676 v_act_link = v_link_best;
4677 v_act =
static_cast<BMVert *
>(v_act_link->
data);
4685 v_act =
static_cast<BMVert *
>(v_act_link->
data);
4701 MEM_mallocN(
sizeof(*ele_sort) * verts_len, __func__));
4703 for (v_link =
static_cast<LinkData *
>(
verts->first), i = 0; v_link;
4704 v_link = v_link->
next, i++)
4709 ele_sort[i].
data =
v;
4719 if ((ele_sort[2].sort_value - ele_sort[verts_len - 1].sort_value) > eps_even) {
4720 for (i = 0; i < 4; i++) {
4726 for (v_link =
static_cast<LinkData *
>(
verts->first), i = 0; i < verts_len / 2;
4727 v_link = v_link->
next, i++)
4743 for (i = 0; i < span; i++) {
4766 for (
uint ob_index = 0; ob_index < objects.size(); ob_index++) {
4768 Object *obedit = objects[ob_index];
4774 bool use_prepare =
true;
4776 const int totedge_orig = em->
bm->
totedge;
4777 const int totface_orig = em->
bm->
totface;
4815 "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b",
4846 params.calc_looptris =
true;
4847 params.calc_normals =
false;
4848 params.is_destructive =
true;
4872 prop =
RNA_def_int(
ot->
srna,
"span", 1, 1, 1000,
"Span",
"Number of grid columns", 1, 100);
4880 "Vertex that is the corner of the grid",
4885 "use_interp_simple",
4888 "Use simple interpolation of grid vertices");
4906 for (
Object *obedit : objects) {
4914 em, op,
"faces.out",
true,
"holes_fill edges=%he sides=%i",
BM_ELEM_SELECT, sides))
4920 params.calc_looptris =
true;
4921 params.calc_normals =
false;
4922 params.is_destructive =
true;
4949 "Number of sides in hole required to fill (zero fills all holes)",
4967 const float angle_max =
M_PI;
4971 for (
Object *obedit : objects) {
4978 if (angle_limit >= angle_max) {
4995 em, op,
"geom.out",
true,
"beautify_fill faces=%hf edges=%he",
BM_ELEM_SELECT, hflag))
5001 params.calc_looptris =
true;
5002 params.calc_normals =
false;
5003 params.is_destructive =
true;
5015 ot->
name =
"Beautify Faces";
5016 ot->
idname =
"MESH_OT_beautify_fill";
5017 ot->
description =
"Rearrange some faces to try to get less degenerated geometry";
5056 for (
Object *obedit : objects) {
5067 "poke faces=%hf offset=%f use_relative_offset=%b center_mode=%i",
5070 use_relative_offset,
5086 params.calc_looptris =
true;
5087 params.calc_normals =
true;
5088 params.is_destructive =
true;
5102 "Weighted median face center"},
5105 {0,
nullptr, 0,
nullptr,
nullptr},
5121 ot->
srna,
"offset", 0.0f, -1e3f, 1e3f,
"Poke Offset",
"Poke Offset", -1.0f, 1.0f);
5123 "use_relative_offset",
5126 "Scale the offset by surrounding geometry");
5132 "Poke face center calculation");
5150 for (
Object *obedit : objects) {
5166 "triangulate faces=%hf quad_method=%i ngon_method=%i",
5190 params.calc_looptris =
true;
5191 params.calc_normals =
false;
5192 params.is_destructive =
true;
5202 ot->
name =
"Triangulate Faces";
5203 ot->
idname =
"MESH_OT_quads_convert_to_tris";
5218 "Method for splitting the quads into triangles");
5224 "Method for splitting the n-gons into triangles");
5247 float angle_face_threshold, angle_shape_threshold;
5252 is_face_pair = (totelem_sel[2] == 2);
5261 angle_face_threshold =
DEG2RADF(180.0f);
5269 angle_shape_threshold =
DEG2RADF(180.0f);
5276 for (
Object *obedit : objects) {
5290 "join_triangles faces=%hf angle_face_threshold=%f angle_shape_threshold=%f "
5291 "cmp_seam=%b cmp_sharp=%b cmp_uvs=%b cmp_vcols=%b cmp_materials=%b",
5293 angle_face_threshold,
5294 angle_shape_threshold,
5307 params.calc_looptris =
true;
5308 params.calc_normals =
false;
5309 params.is_destructive =
true;
5339 "Shape angle limit",
5354 ot->
name =
"Tris to Quads";
5355 ot->
idname =
"MESH_OT_tris_convert_to_quads";
5383 const float vertex_group_factor =
RNA_float_get(op->
ptr,
"vertex_group_factor");
5386 const float symmetry_eps = 0.00002f;
5387 const int symmetry_axis = use_symmetry ?
RNA_enum_get(op->
ptr,
"symmetry_axis") : -1;
5390 if (ratio == 1.0f) {
5399 for (
Object *obedit : objects) {
5406 float *vweights =
static_cast<float *
>(
MEM_mallocN(
sizeof(*vweights) *
bm->
totvert, __func__));
5411 if (use_vertex_group && (cd_dvert_offset == -1)) {
5413 use_vertex_group =
false;
5420 float weight = 0.0f;
5422 if (use_vertex_group) {
5426 if (invert_vertex_group) {
5427 weight = 1.0f - weight;
5435 vweights[i] = weight;
5444 ratio_adjust = ratio;
5455 int totface_basis = 0;
5456 int totface_adjacent = 0;
5461 const int f_len = f->
len > 4 ? (f->
len - 2) : 1;
5462 totface_basis += f_len;
5464 BMLoop *l_iter, *l_first;
5468 totface_adjacent += f_len;
5471 }
while ((l_iter = l_iter->
next) != l_first);
5474 ratio_adjust = ratio;
5475 ratio_adjust = 1.0f - ratio_adjust;
5476 ratio_adjust *=
float(totface_adjacent) /
float(totface_basis);
5477 ratio_adjust = 1.0f - ratio_adjust;
5481 em->
bm, ratio_adjust, vweights, vertex_group_factor,
false, symmetry_axis, symmetry_eps);
5494 params.calc_looptris =
true;
5495 params.calc_normals =
true;
5496 params.is_destructive =
true;
5532 ot->
name =
"Decimate Geometry";
5552 "Use active vertex group as an influence");
5554 "vertex_group_factor",
5559 "Vertex group strength",
5563 ot->
srna,
"invert_vertex_group",
false,
"Invert",
"Invert vertex group influence");
5581 ot->
srna,
"use_verts", value,
"Dissolve Vertices",
"Dissolve remaining vertices");
5593 "Split off face corners to maintain surrounding geometry");
5598 "use_boundary_tear",
5601 "Split off face corners instead of merging faces");
5614 for (
Object *obedit : objects) {
5625 "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
5636 params.calc_looptris =
true;
5637 params.calc_normals =
false;
5638 params.is_destructive =
true;
5648 ot->
name =
"Dissolve Vertices";
5649 ot->
description =
"Dissolve vertices, merge edges and faces";
5650 ot->
idname =
"MESH_OT_dissolve_verts";
5678 for (
Object *obedit : objects) {
5689 "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
5700 params.calc_looptris =
true;
5701 params.calc_normals =
false;
5702 params.is_destructive =
true;
5712 ot->
name =
"Dissolve Edges";
5714 ot->
idname =
"MESH_OT_dissolve_edges";
5740 for (
Object *obedit : objects) {
5753 "dissolve_faces faces=%hf use_verts=%b",
5763 params.calc_looptris =
true;
5764 params.calc_normals =
false;
5765 params.is_destructive =
true;
5775 ot->
name =
"Dissolve Faces";
5777 ot->
idname =
"MESH_OT_dissolve_faces";
5821 ot->
name =
"Dissolve Selection";
5822 ot->
description =
"Dissolve geometry based on the selection mode";
5823 ot->
idname =
"MESH_OT_dissolve_mode";
5846 const bool use_dissolve_boundaries =
RNA_boolean_get(op->
ptr,
"use_dissolve_boundaries");
5854 for (
Object *obedit : objects) {
5900 "dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b delimit=%i",
5904 use_dissolve_boundaries,
5910 params.calc_looptris =
true;
5911 params.calc_normals =
false;
5912 params.is_destructive =
true;
5924 ot->
name =
"Limited Dissolve";
5925 ot->
idname =
"MESH_OT_dissolve_limited";
5927 "Dissolve selected edges and vertices, limited by the angle of surrounding geometry";
5948 "use_dissolve_boundaries",
5951 "Dissolve all vertices in between face boundaries");
5957 "Delimit dissolve operation");
5970 int totelem_old[3] = {0, 0, 0};
5971 int totelem_new[3] = {0, 0, 0};
5976 for (
Object *obedit : objects) {
5986 for (
Object *obedit : objects) {
5998 params.calc_looptris =
true;
5999 params.calc_normals =
false;
6000 params.is_destructive =
true;
6016 ot->
name =
"Degenerate Dissolve";
6017 ot->
idname =
"MESH_OT_dissolve_degenerate";
6018 ot->
description =
"Dissolve zero area faces and zero length edges";
6033 "Maximum distance between elements to merge",
6053 for (
Object *obedit : objects) {
6079 "dissolve_edges edges=%he use_verts=%b use_face_split=%b",
6092 params.calc_looptris =
true;
6093 params.calc_normals =
false;
6094 params.is_destructive =
true;
6104 ot->
name =
"Delete Edge Loop";
6105 ot->
description =
"Delete an edge loop by merging the faces on each side";
6106 ot->
idname =
"MESH_OT_delete_edgeloop";
6119 "Split off face corners to maintain surrounding geometry");
6134 for (
Object *obedit : objects) {
6156 params.calc_looptris =
true;
6157 params.calc_normals =
true;
6158 params.is_destructive =
true;
6170 ot->
description =
"Split off selected geometry from connected unselected geometry";
6242 char *pblock[3] = {
nullptr,
nullptr,
nullptr}, *pb;
6243 BMElemSort *sblock[3] = {
nullptr,
nullptr,
nullptr}, *sb;
6244 uint *map[3] = {
nullptr,
nullptr,
nullptr}, *mp;
6245 int totelem[3] = {0, 0, 0};
6246 int affected[3] = {0, 0, 0};
6249 if (!(types &&
flag && action)) {
6265 float fact = reverse ? -1.0 : 1.0;
6272 pb = pblock[0] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[0], __func__));
6282 sb[affected[0]].org_idx = i;
6283 sb[affected[0]++].srt = co[coidx] * fact;
6292 pb = pblock[1] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[1], __func__));
6303 sb[affected[1]].org_idx = i;
6304 sb[affected[1]++].srt = co[coidx] * fact;
6313 pb = pblock[2] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[2], __func__));
6324 sb[affected[2]].org_idx = i;
6325 sb[affected[2]++].srt = co[coidx] * fact;
6337 float fact = reverse ? -1.0 : 1.0;
6345 pb = pblock[0] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[0], __func__));
6362 pb = pblock[1] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[1], __func__));
6372 sb[affected[1]].org_idx = i;
6382 pb = pblock[2] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[2], __func__));
6392 sb[affected[2]].org_idx = i;
6404 pb = pblock[2] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[2], __func__));
6414 sb[affected[2]].org_idx = i;
6417 sb[affected[2]++].srt = srt *
float(totelem[2]) +
float(i);
6427 uint *tbuf[3] = {
nullptr,
nullptr,
nullptr}, *tb;
6430 tb = tbuf[0] =
static_cast<uint *
>(
MEM_callocN(
sizeof(
int) * totelem[0], __func__));
6431 mp = map[0] =
static_cast<uint *
>(
MEM_callocN(
sizeof(
int) * totelem[0], __func__));
6435 mp[affected[0]++] = i;
6445 tb = tbuf[1] =
static_cast<uint *
>(
MEM_callocN(
sizeof(
int) * totelem[1], __func__));
6446 mp = map[1] =
static_cast<uint *
>(
MEM_callocN(
sizeof(
int) * totelem[1], __func__));
6450 mp[affected[1]++] = i;
6460 tb = tbuf[2] =
static_cast<uint *
>(
MEM_callocN(
sizeof(
int) * totelem[2], __func__));
6461 mp = map[2] =
static_cast<uint *
>(
MEM_callocN(
sizeof(
int) * totelem[2], __func__));
6465 mp[affected[2]++] = i;
6475 int tot = totelem[j];
6476 int aff = affected[j];
6482 if (
ELEM(aff, 0, tot)) {
6489 memcpy(tb + (tot - aff), mp, aff *
sizeof(
int));
6492 memcpy(mp + aff, tb, (tot - aff) *
sizeof(
int));
6494 mp = map[j] = tbuf[j];
6499 for (i = tot, tb = tbuf[j] + tot - 1; i--; tb--) {
6511 pb = pblock[0] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[0], __func__));
6531 pb = pblock[1] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[1], __func__));
6551 pb = pblock[2] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[2], __func__));
6572 pb = pblock[0] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[0], __func__));
6580 sb[affected[0]++].srt =
float(-i);
6589 pb = pblock[1] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[1], __func__));
6597 sb[affected[1]++].srt =
float(-i);
6606 pb = pblock[2] =
static_cast<char *
>(
MEM_callocN(
sizeof(
char) * totelem[2], __func__));
6614 sb[affected[2]++].srt =
float(-i);
6626 if (affected[0] == 0 && affected[1] == 0 && affected[2] == 0) {
6645 if (pb && sb && !map[j]) {
6648 int tot = totelem[j];
6649 int aff = affected[j];
6653 mp = map[j] =
static_cast<uint *
>(
MEM_mallocN(
sizeof(
int) * tot, __func__));
6654 p_blk = pb + tot - 1;
6655 s_blk = sb + aff - 1;
6656 for (i = tot; i--; p_blk--) {
6677 params.calc_looptris = (totelem[2] != 0);
6678 params.calc_normals =
false;
6679 params.is_destructive =
true;
6708 if (rv3d ==
nullptr) {
6735 for (
uint ob_index = 0; ob_index < objects.size(); ob_index++) {
6736 Object *ob = objects[ob_index];
6747 int seed_iter =
seed;
6755 C, scene, ob, rv3d, elem_types,
BM_ELEM_SELECT, action, use_reverse, seed_iter);
6768 if (
STREQ(prop_id,
"seed")) {
6776 if (
STREQ(prop_id,
"reverse")) {
6793 "Sort selected elements from farthest to nearest one in current view"},
6798 "Sort selected elements from left to right one in current view"},
6803 "Sort selected elements from nearest to farthest from 3D cursor"},
6808 "Sort selected faces from smallest to greatest material index"},
6813 "Move all selected elements in first places, preserving their relative order.\n"
6814 "Warning: This will affect unselected elements' indices as well"},
6815 {
SRT_RANDOMIZE,
"RANDOMIZE", 0,
"Randomize",
"Randomize order of selected elements"},
6816 {
SRT_REVERSE,
"REVERSE", 0,
"Reverse",
"Reverse current order of selected elements"},
6817 {0,
nullptr, 0,
nullptr,
nullptr},
6821 {
BM_VERT,
"VERT", 0,
"Vertices",
""},
6822 {
BM_EDGE,
"EDGE", 0,
"Edges",
""},
6823 {
BM_FACE,
"FACE", 0,
"Faces",
""},
6824 {0,
nullptr, 0,
nullptr,
nullptr},
6828 ot->
name =
"Sort Mesh Elements";
6830 "The order of selected vertices/edges/faces is modified, based on a given method";
6831 ot->
idname =
"MESH_OT_sort_elements";
6848 "Type of reordering operation to apply");
6854 "Which elements to affect (vertices, edges and/or faces)");
6856 RNA_def_int(
ot->
srna,
"seed", 0, 0, INT_MAX,
"Seed",
"Seed for random-based operations", 0, 255);
6877 int totface_del = 0;
6888 bool is_all_sel =
true;
6903 if (is_all_sel ==
false) {
6916 const bool use_pairs,
6917 const bool use_cyclic,
6918 const bool use_merge,
6919 const float merge_factor,
6920 const int twist_offset)
6924 int totface_del = 0;
6925 BMFace **totface_del_arr =
nullptr;
6927 bool changed =
false;
6944 totface_del_arr =
static_cast<BMFace **
>(
6945 MEM_mallocN(
sizeof(*totface_del_arr) * totface_del, __func__));
6950 totface_del_arr[i++] = f;
6962 "bridge_loops edges=%he use_pairs=%b use_cyclic=%b use_merge=%b merge_factor=%f "
6971 if (use_faces && totface_del) {
6974 for (i = 0; i < totface_del; i++) {
6979 "delete geom=%hf context=%i",
6989 if (use_merge ==
false) {
6997 if (use_merge ==
false) {
7001 if (op_props.
cuts) {
7009 "subdivide_edgering edges=%S interp_mode=%i cuts=%i smooth=%f "
7010 "profile_shape=%i profile_shape_factor=%f",
7028 if (totface_del_arr) {
7038 params.calc_looptris =
true;
7039 params.calc_normals =
false;
7040 params.is_destructive =
true;
7061 for (
Object *obedit : objects) {
7070 static_cast<Mesh *
>(obedit->data),
7086 {0,
nullptr, 0,
nullptr,
nullptr},
7090 ot->
name =
"Bridge Edge Loops";
7091 ot->
description =
"Create a bridge of faces between two or more selected edge loops";
7092 ot->
idname =
"MESH_OT_bridge_edge_loops";
7106 "Method of bridging multiple loops");
7109 RNA_def_float(
ot->
srna,
"merge_factor", 0.5f, 0.0f, 1.0f,
"Merge Factor",
"", 0.0f, 1.0f);
7116 "Twist offset for closed loops",
7144 for (
Object *obedit : objects) {
7156 "wireframe faces=%hf use_replace=%b use_boundary=%b use_even_offset=%b "
7157 "use_relative_offset=%b "
7158 "use_crease=%b crease_weight=%f thickness=%f offset=%f",
7163 use_relative_offset,
7180 params.calc_looptris =
true;
7181 params.calc_normals =
false;
7182 params.is_destructive =
true;
7211 "Scale the offset to give more even thickness");
7213 "use_relative_offset",
7216 "Scale the offset by surrounding geometry");
7219 ot->
srna,
"thickness", 0.01f, 0.0f, 1e4f,
"Thickness",
"", 0.0f, 10.0f);
7227 "Crease hub edges for an improved subdivision surface");
7229 ot->
srna,
"crease_weight", 0.01f, 0.0f, 1e3f,
"Crease Weight",
"", 0.0f, 1.0f);
7242 bool changed_multi =
false;
7247 for (
Base *base : bases) {
7248 Object *obedit = base->object;
7259 "offset_edgeloops edges=%he use_cap_endpoint=%b",
7272 params.calc_looptris =
true;
7273 params.calc_normals =
false;
7274 params.is_destructive =
true;
7276 changed_multi =
true;
7280 if (changed_multi) {
7297 ot->
name =
"Offset Edge Loop";
7298 ot->
idname =
"MESH_OT_offset_edge_loops";
7299 ot->
description =
"Create offset edge loop from the current selection";
7312 ot->
srna,
"use_cap_endpoint",
false,
"Cap Endpoint",
"Extend loop around end-points");
7336 for (
Object *obedit : objects) {
7348 "convex_hull input=%hvef "
7349 "use_existing_faces=%b",
7351 use_existing_faces);
7364 if (delete_unused) {
7366 em, op,
"delete geom=%S context=%i", &bmop,
"geom_unused.out",
DEL_ONLYTAGGED))
7376 em, op,
"delete geom=%S context=%i", &bmop,
"geom_holes.out",
DEL_ONLYTAGGED))
7384 if (join_triangles) {
7389 "join_triangles faces=%S "
7390 "angle_face_threshold=%f angle_shape_threshold=%f",
7393 angle_face_threshold,
7394 angle_shape_threshold))
7406 params.calc_looptris =
true;
7407 params.calc_normals =
false;
7408 params.is_destructive =
true;
7419 ot->
name =
"Convex Hull";
7420 ot->
description =
"Enclose selected vertices in a convex polyhedron";
7421 ot->
idname =
"MESH_OT_convex_hull";
7424 ot->
exec = edbm_convex_hull_exec;
7435 "Delete selected elements that are not used by the hull");
7438 "use_existing_faces",
7440 "Use Existing Faces",
7441 "Skip hull triangles that are covered by a pre-existing face");
7447 "Delete selected faces that are used by the hull");
7450 ot->
srna,
"join_triangles",
true,
"Join Triangles",
"Merge adjacent triangles into quads");
7470 for (
Object *obedit : objects) {
7481 "symmetrize input=%hvef direction=%i dist=%f",
7496 params.calc_looptris =
true;
7497 params.calc_normals =
false;
7498 params.is_destructive =
true;
7510 ot->
description =
"Enforce symmetry (both form and topological) across an axis";
7525 "Which sides to copy from and to");
7532 "Limit for snap middle vertices to the axis center",
7545 const float eps = 0.00001f;
7546 const float eps_sq =
eps *
eps;
7547 const bool use_topology =
false;
7555 int totvertfound = 0, totvertmirr = 0, totvertfail = 0, totobjects = 0;
7558 int axis = axis_dir % 3;
7559 bool axis_sign = axis != axis_dir;
7566 for (
Object *obedit : objects) {
7598 int i_mirr = index[i];
7604 float co[3], co_mirr[3];
7606 if ((
v->
co[axis] > v_mirr->
co[axis]) == axis_sign) {
7607 std::swap(
v, v_mirr);
7611 co_mirr[axis] *= -1.0f;
7647 params.calc_looptris =
false;
7648 params.calc_normals =
false;
7649 params.is_destructive =
false;
7659 "%d already symmetrical, %d pairs mirrored, %d failed",
7660 totvertfound - totvertmirr,
7664 else if (totobjects) {
7667 "%d already symmetrical, %d pairs mirrored",
7668 totvertfound - totvertmirr,
7678 ot->
name =
"Snap to Symmetry";
7679 ot->
description =
"Snap vertex pairs to their mirrored locations";
7680 ot->
idname =
"MESH_OT_symmetry_snap";
7694 "Which sides to copy from and to");
7701 "Distance within which matching vertices are searched",
7710 "Mix factor of the locations of the vertices",
7714 ot->
srna,
"use_center",
true,
"Center",
"Snap middle vertices to the axis center");
7719#if defined(WITH_FREESTYLE)
7736 for (
Object *obedit : objects) {
7739 if (em ==
nullptr) {
7758 fed->
flag &= ~FREESTYLE_EDGE_MARK;
7784 ot->
name =
"Mark Freestyle Edge";
7785 ot->
description =
"(Un)mark selected edges as Freestyle feature edges";
7786 ot->
idname =
"MESH_OT_mark_freestyle_edge";
7789 ot->
exec = edbm_mark_freestyle_edge_exec;
7816 for (
Object *obedit : objects) {
7819 if (em ==
nullptr) {
7836 ffa->
flag &= ~FREESTYLE_FACE_MARK;
7862 ot->
name =
"Mark Freestyle Face";
7863 ot->
description =
"(Un)mark selected faces for exclusion from Freestyle feature edge detection";
7864 ot->
idname =
"MESH_OT_mark_freestyle_face";
7867 ot->
exec = edbm_mark_freestyle_face_exec;
7918 "Toggle inversion of affected normals"},
7923 "Interpolate between new and original normals"},
7930 "Follow mouse cursor position"},
7935 "Use current rotation/scaling pivot point coordinates"},
7940 "Use current edited object's location"},
7944 "Set and Use 3D Cursor",
7945 "Set new 3D cursor position and use it"},
7949 "Select and Use Mesh Item",
7950 "Select new active mesh element and use its location"},
7951 {0,
nullptr, 0,
nullptr,
nullptr},
7953 static const char *keymap_name =
"Custom Normals Modal Map";
7969#define CLNORS_VALID_VEC_LEN (1e-4f)
7987 "Use static coordinates (defined by various means)"},
7989 {0,
nullptr, 0,
nullptr,
nullptr},
8004 return (lnors_ed_arr->
totloop != 0);
8032 auto get_modal_key_str = [&](
int id) {
8036 const std::string header = fmt::format(
8037 IFACE_(
"{}: confirm, {}: cancel, "
8038 "{}: point to mouse ({}), {}: point to Pivot, "
8039 "{}: point to object origin, {}: reset normals, "
8040 "{}: set & point to 3D cursor, {}: select & point to mesh item, "
8041 "{}: invert normals ({}), {}: spherize ({}), {}: align ({})"),
8089 if (do_align && !do_reset) {
8096 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
8100 else if (do_spherize) {
8104 float spherized_normal[3];
8115 else if (do_align) {
8122 if (do_invert && !do_reset) {
8151 int new_mode = mode;
8152 bool force_mousemove =
false;
8153 bool do_reset =
false;
8158 switch (event->
val) {
8204 force_mousemove =
true;
8237 switch (scene->toolsettings->transform_pivot_point) {
8242 float min[3], max[3];
8291 if (new_mode != mode) {
8318 params.calc_looptris =
true;
8319 params.calc_normals =
false;
8320 params.is_destructive =
false;
8381 params.calc_looptris =
true;
8382 params.calc_normals =
false;
8383 params.is_destructive =
false;
8395 if (
STREQ(prop_id,
"spherize_strength")) {
8425 ot->
name =
"Point Normals to Target";
8426 ot->
description =
"Point selected custom normals to specified Target";
8427 ot->
idname =
"MESH_OT_point_normals";
8445 "How to define coordinates to point custom normals to");
8459 "Target location to which normals will point",
8464 ot->
srna,
"spherize",
false,
"Spherize",
"Interpolate between original and new normals");
8467 "spherize_strength",
8471 "Spherize Strength",
8472 "Ratio of spherized normal to original normal",
8493 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
8504 float avg_normal[3] = {0.0f, 0.0f, 0.0f};
8507 for (; loops; loops = loops->next) {
8562 const BMEdge *e_org = l_curr->
e;
8563 BMLoop *lfan_pivot, *lfan_pivot_next;
8565 lfan_pivot = l_curr;
8566 e_next = lfan_pivot->
e;
8567 float avg_normal[3] = {0.0f};
8571 if (lfan_pivot_next) {
8575 e_next = (lfan_pivot->
e == e_next) ? lfan_pivot->
prev->
e : lfan_pivot->
e;
8584 lfan_pivot = lfan_pivot_next;
8598 }
while ((l_curr = l_curr->
next) != l_first);
8609 for (
Object *obedit : objects) {
8647 params.calc_looptris =
true;
8648 params.calc_normals =
false;
8649 params.is_destructive =
false;
8664 ot->
name =
"Merge Normals";
8665 ot->
description =
"Merge custom normals of selected vertices";
8666 ot->
idname =
"MESH_OT_merge_normals";
8684 ot->
name =
"Split Normals";
8685 ot->
description =
"Split custom normals of selected vertices";
8686 ot->
idname =
"MESH_OT_split_normals";
8713 "Take average of vertex normals"},
8718 "Set all vertex normals by face area"},
8723 "Set all vertex normals by corner angle"},
8724 {0,
nullptr, 0,
nullptr,
nullptr},
8740 for (
uint ob_index = 0; ob_index < objects.size(); ob_index++) {
8744 Object *obedit = objects[ob_index];
8756 float weight = absweight / 50.0f;
8757 if (absweight == 100.0f) {
8758 weight =
float(SHRT_MAX);
8760 else if (absweight == 1.0f) {
8761 weight = 1 /
float(SHRT_MAX);
8763 else if ((weight - 1) * 25 > 1) {
8764 weight = (weight - 1) * 25;
8788 const BMEdge *e_org = l_curr->
e;
8789 BMLoop *lfan_pivot, *lfan_pivot_next;
8791 lfan_pivot = l_curr;
8792 e_next = lfan_pivot->
e;
8796 if (lfan_pivot_next) {
8800 e_next = (lfan_pivot->
e == e_next) ? lfan_pivot->
prev->
e : lfan_pivot->
e;
8816 lfan_pivot = lfan_pivot_next;
8819 float wnor[3], avg_normal[3] = {0.0f},
count = 0;
8831 const float n_weight =
pow(weight,
count);
8842 mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
8858 }
while ((l_curr = l_curr->
next) != l_first);
8862 params.calc_looptris =
true;
8863 params.calc_normals =
false;
8864 params.is_destructive =
false;
8882 if (
STREQ(prop_id,
"weight")) {
8883 return !is_clor_average_loop;
8885 if (
STREQ(prop_id,
"threshold")) {
8886 return !is_clor_average_loop;
8915 ot->
name =
"Average Normals";
8916 ot->
description =
"Average custom normals of selected vertices";
8917 ot->
idname =
"MESH_OT_average_normals";
8932 "Averaging method");
8934 RNA_def_int(
ot->
srna,
"weight", 50, 1, 100,
"Weight",
"Weight applied per face", 1, 100);
8942 "Threshold value for different weights to be considered equal",
8967 "Paste normal from the internal clipboard"},
8973 "Multiply normal vector with selection"},
8978 "Reset the internal clipboard and/or normal of selected element"},
8979 {0,
nullptr, 0,
nullptr,
nullptr},
8990 float *normal_vector = scene->toolsettings->normal_vector;
8991 bool done_copy =
false;
8993 for (
Object *obedit : objects) {
9017 "Can only copy one custom normal, vertex normal or face normal");
9021 if (lnors_ed_arr->
totloop == 1) {
9036 bool are_same_lnors =
true;
9037 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
9039 are_same_lnors =
false;
9042 if (are_same_lnors) {
9056 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
9058 float abs_normal[3];
9080 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
9094 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
9109 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
9124 params.calc_looptris =
true;
9125 params.calc_normals =
false;
9126 params.is_destructive =
false;
9139 if (
STREQ(prop_id,
"absolute")) {
9167 ot->
name =
"Normals Vector Tools";
9168 ot->
description =
"Custom normals tools using Normal Vector of UI";
9169 ot->
idname =
"MESH_OT_normals_tools";
9184 "Mode of tools taking input from interface");
9190 "Absolute Coordinates",
9191 "Copy Absolute coordinates of Normal vector");
9207 for (
Object *obedit : objects) {
9218 BMIter fiter, viter, eiter, liter;
9224 float(*vert_normals)[3] =
static_cast<float(*)[3]
>(
9256 for (; loops; loops = loops->next) {
9281 params.calc_looptris =
true;
9282 params.calc_normals =
false;
9283 params.is_destructive =
false;
9293 ot->
name =
"Set Normals from Faces";
9294 ot->
description =
"Set the custom normals from the selected faces ones";
9295 ot->
idname =
"MESH_OT_set_normals_from_faces";
9305 ot->
srna,
"keep_sharp",
false,
"Keep Sharp Edges",
"Do not set sharp edges to face");
9321 for (
Object *obedit : objects) {
9331 float(*smooth_normal)[3] =
static_cast<float(*)[3]
>(
9342 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
9344 float loop_normal[3];
9350 short *clnors =
static_cast<short *
>(
9354 add_v3_v3(smooth_normal[i], loop_normal);
9362 for (
int i = 0; i < lnors_ed_arr->
totloop; i++, lnor_ed++) {
9363 float current_normal[3];
9375 mul_v3_fl(current_normal, 1.0f - factor);
9377 add_v3_v3(current_normal, smooth_normal[i]);
9392 params.calc_looptris =
true;
9393 params.calc_normals =
false;
9394 params.is_destructive =
false;
9404 ot->
name =
"Smooth Normals Vectors";
9405 ot->
description =
"Smooth custom normals based on adjacent vertex normals";
9406 ot->
idname =
"MESH_OT_smooth_normals";
9421 "Specifies weight of smooth vs original normal",
9439 for (
Object *obedit : objects) {
9451 if (cd_prop_int_index == -1) {
9465 *strength = face_strength;
9472 if (*strength == face_strength) {
9483 params.calc_looptris =
false;
9484 params.calc_normals =
false;
9485 params.is_destructive =
false;
9496 {0,
nullptr, 0,
nullptr,
nullptr},
9502 ot->
name =
"Face Normals Strength";
9503 ot->
description =
"Set/Get strength of face (used in Weighted Normal modifier)";
9504 ot->
idname =
"MESH_OT_mod_weighted_strength";
9521 "Strength to use for assigning or selecting face influence for weighted normal modifier");
9527 ot->
name =
"Flip Quad Tessellation";
9528 ot->
description =
"Flips the tessellation of selected quads";
9529 ot->
idname =
"MESH_OT_flip_quad_tessellation";
int BKE_attribute_to_index(const AttributeOwner &owner, const CustomDataLayer *layer, AttrDomainMask domain_mask, eCustomDataMask layer_mask)
@ ATTR_DOMAIN_MASK_CORNER
const struct CustomDataLayer * BKE_attribute_search(const AttributeOwner &owner, const char *name, eCustomDataMask type, AttrDomainMask domain_mask)
#define CTX_DATA_BEGIN(C, Type, instance, member)
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
int CustomData_get_n_offset(const CustomData *data, eCustomDataType type, int n)
void * CustomData_bmesh_get_n(const CustomData *data, void *block, eCustomDataType type, int n)
int CustomData_get_named_layer_index(const CustomData *data, eCustomDataType type, blender::StringRef name)
void * CustomData_bmesh_get(const CustomData *data, void *block, eCustomDataType type)
int CustomData_get_layer_index(const CustomData *data, eCustomDataType type)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
void BKE_editmesh_lnorspace_update(BMEditMesh *em)
KeyBlock * BKE_keyblock_find_name(Key *key, const char name[])
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
blender::Vector< Base * > BKE_view_layer_array_from_bases_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
General operations, lookup, etc. for materials.
struct Material *** BKE_id_material_array_p(struct ID *id)
short * BKE_object_material_len_p(struct Object *ob)
void BKE_object_material_resize(struct Main *bmain, struct Object *ob, short totcol, bool do_id_user)
struct Material *** BKE_object_material_array_p(struct Object *ob)
void BKE_object_material_array_assign(struct Main *bmain, struct Object *ob, struct Material ***matar, int totcol, bool to_object_only)
void BKE_id_material_clear(struct Main *bmain, struct ID *id)
short * BKE_id_material_len_p(struct ID *id)
void BKE_id_material_resize(struct Main *bmain, struct ID *id, short totcol, bool do_id_user)
void BKE_lnor_space_custom_data_to_normal(const MLoopNorSpace *lnor_space, const short clnor_data[2], float r_custom_lnor[3])
@ MLNOR_SPACEARR_BMLOOP_PTR
void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space, const float custom_lnor[3], short r_clnor_data[2])
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_original_mesh(const Object *object)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_BITMAP_NEW(_num, _alloc_string)
#define BLI_BITMAP_TEST(_bitmap, _index)
#define BLI_BITMAP_ENABLE(_bitmap, _index)
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
A min-heap / priority queue ADT.
HeapSimple * BLI_heapsimple_new(void) ATTR_WARN_UNUSED_RESULT
void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1)
float BLI_heapsimple_top_value(const HeapSimple *heap) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_heapsimple_pop_min(HeapSimple *heap) ATTR_NONNULL(1)
bool BLI_heapsimple_is_empty(const HeapSimple *heap) ATTR_NONNULL(1)
void BLI_heapsimple_insert(HeapSimple *heap, float value, void *ptr) ATTR_NONNULL(1)
BLI_LINKSTACK_*** wrapper macros for using a LinkNode to store a stack of pointers,...
#define BLI_SMALLSTACK_DECLARE(var, type)
#define BLI_SMALLSTACK_POP(var)
#define BLI_SMALLSTACK_PUSH(var, data)
#define BLI_SMALLSTACK_IS_EMPTY(var)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void BLI_listbase_rotate_first(struct ListBase *lb, void *vlink) ATTR_NONNULL(1
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count_at_most(const struct ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findptr(const struct ListBase *listbase, const void *ptr, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int mod_i(int i, int n)
MINLINE int compare_ff(float a, float b, float max_diff)
int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
MINLINE void negate_v3(float r[3])
MINLINE bool compare_v3v3(const float v1[3], const float v2[3], float limit) ATTR_WARN_UNUSED_RESULT
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
struct RNG * BLI_rng_new_srandom(unsigned int seed)
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_sortutil_cmp_float_reverse(const void *a_, const void *b_)
#define UNUSED_VARS_NDEBUG(...)
#define BLT_I18NCONTEXT_ID_CURVE_LEGACY
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_GEOMETRY_ALL_MODES
#define CD_MASK_COLOR_ALL
@ MOD_TRIANGULATE_QUAD_BEAUTY
#define MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID
@ MOD_TRIANGULATE_NGON_BEAUTY
Object is a sort of wrapper for general info.
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_CENTER_MEDIAN
@ OP_IS_MODAL_GRAB_CURSOR
void EDBM_flag_disable_all(BMEditMesh *em, char hflag)
void EDBM_automerge(Object *obedit, bool update, char hflag, float dist)
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)
BMVert * EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v)
void EDBM_verts_mirror_cache_begin(BMEditMesh *em, int axis, bool use_self, bool use_select, bool respecthide, bool use_topology)
void void void EDBM_redo_state_free(BMBackup *backup) ATTR_NONNULL(1)
void EDBM_mesh_normals_update(BMEditMesh *em)
bool EDBM_mesh_reveal(BMEditMesh *em, bool select)
bool EDBM_mesh_hide(BMEditMesh *em, bool swap)
void EDBM_mesh_stats_multi(blender::Span< Object * > objects, int totelem[3], int totelem_sel[3])
void ED_mesh_geometry_clear(Mesh *mesh)
void EDBM_verts_mirror_apply(BMEditMesh *em, int sel_from, int sel_to)
void EDBM_selectmode_flush(BMEditMesh *em)
BMBackup EDBM_redo_state_store(BMEditMesh *em)
void EDBM_selectmode_flush_ex(BMEditMesh *em, short selectmode)
void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, int axis, bool use_self, bool use_select, bool respecthide, bool use_topology, float maxdist, int *r_index)
void EDBM_verts_mirror_cache_end(BMEditMesh *em)
bool EDBM_selectmode_disable_multi_ex(Scene *scene, blender::Span< Base * > bases, short selectmode_disable, short selectmode_fallback)
void EDBM_select_flush(BMEditMesh *em)
bool EDBM_select_pick(bContext *C, const int mval[2], const SelectPick_Params *params)
void ED_outliner_select_sync_from_object_tag(bContext *C)
void ED_area_status_text(ScrArea *area, const char *str)
bool ED_operator_scene_editable(bContext *C)
bool ED_operator_editmesh(bContext *C)
void ED_uvedit_live_unwrap(const Scene *scene, blender::Span< Object * > objects)
RegionView3D * ED_view3d_context_rv3d(bContext *C)
void ED_view3d_win_to_3d_int(const View3D *v3d, const ARegion *region, const float depth_pt[3], const int mval[2], float r_out[3])
void view3d_operator_needs_opengl(const bContext *C)
void ED_view3d_cursor3d_update(bContext *C, const int mval[2], bool use_depth, enum eV3DCursorOrient orientation)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Read Guarded memory(de)allocation.
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
@ UI_BUT_LABEL_ALIGN_NONE
eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr, bool(*check_prop)(PointerRNA *ptr, PropertyRNA *prop, void *user_data), void *user_data, PropertyRNA *prop_activate_init, eButLabelAlign label_align, bool compact)
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
#define BM_elem_cb_check_hflag_disabled_simple(type, hflag_n)
#define BM_DISK_EDGE_NEXT(e, v)
#define BM_FACE_FIRST_LOOP(p)
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst, BMesh *bm_src, const char htype, const BMAllocTemplate *allocsize)
void BM_vert_separate(BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select, BMVert ***r_vout, int *r_vout_len)
void BM_vert_kill(BMesh *bm, BMVert *v)
void BM_face_kill(BMesh *bm, BMFace *f)
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
void BM_mesh_decimate_collapse(BMesh *bm, float factor, float *vweights, float vweight_factor, bool do_triangulate, int symmetry_axis, float symmetry_eps)
BM_mesh_decimate.
void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
void BM_mesh_edgeloops_free(ListBase *eloops)
int BM_mesh_edgeloops_find(BMesh *bm, ListBase *r_eloops, bool(*test_fn)(BMEdge *, void *user_data), void *user_data)
int BM_edgeloop_length_get(BMEdgeLoopStore *el_store)
bool BM_edgeloop_is_closed(BMEdgeLoopStore *el_store)
void BM_edgeloop_edges_get(BMEdgeLoopStore *el_store, BMEdge **e_arr)
ListBase * BM_edgeloop_verts_get(BMEdgeLoopStore *el_store)
bool BMO_error_occurred_at_level(BMesh *bm, eBMOpErrorLevel level)
#define BM_elem_index_get(ele)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_flag_set(ele, hflag, val)
#define BM_elem_index_set(ele, index)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_test_bool(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
void * BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value)
Elem Iter Flag Count.
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMVert * BM_mesh_active_vert_get(BMesh *bm)
void BM_select_history_clear(BMesh *bm)
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
Select Face.
void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
Select Vert.
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
Select Edge.
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag, const bool respecthide, const bool overwrite, const char hflag_test)
#define BM_select_history_store_notest(bm, ele)
#define BM_select_history_store_head_notest(bm, ele)
#define BM_select_history_store(bm, ele)
#define BM_SELECT_HISTORY_BACKUP(bm)
#define BM_SELECT_HISTORY_RESTORE(bm)
const BMAllocTemplate bm_mesh_allocsize_default
void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx)
void BM_mesh_elem_toolflags_ensure(BMesh *bm)
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const BMeshCreateParams *params)
BMesh Make Mesh.
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *mesh, const BMeshFromMeshParams *params)
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *mesh, const BMeshToMeshParams *params)
void BM_mesh_copy_arrays(BMesh *bm_src, BMesh *bm_dst, BMVert **verts_src, uint verts_src_len, BMEdge **edges_src, uint edges_src_len, BMFace **faces_src, uint faces_src_len)
void BM_lnorspace_update(BMesh *bm)
void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges)
bool BM_custom_loop_normals_to_vector_layer(BMesh *bm)
void BM_mesh_normals_update(BMesh *bm)
BMLoopNorEditDataArray * BM_loop_normal_editdata_array_init(BMesh *bm, const bool do_all_loops_of_vert)
void BM_loop_normal_editdata_array_free(BMLoopNorEditDataArray *lnors_ed_arr)
bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
void BM_custom_loop_normals_from_vector_layer(BMesh *bm, bool add_sharp_edges)
void * BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int len)
@ BMO_SYMMETRIZE_NEGATIVE_X
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_slot_buffer_hflag_disable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, char hflag, bool do_flush)
BMO_FLAG_BUFFER.
BMOpSlot * BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK GET SLOT.
void BMO_op_exec(BMesh *bm, BMOperator *op)
BMESH OPSTACK EXEC OP.
void * BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void BMO_op_init(BMesh *bm, BMOperator *op, int flag, const char *opname)
BMESH OPSTACK INIT OP.
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
bool BMO_op_initf(BMesh *bm, BMOperator *op, int flag, const char *fmt,...)
void BMO_op_finish(BMesh *bm, BMOperator *op)
BMESH OPSTACK FINISH OP.
int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
bool BMO_op_callf(BMesh *bm, int flag, const char *fmt,...)
@ DEL_FACES_KEEP_BOUNDARY
#define BMO_FLAG_DEFAULTS
@ SUBD_CORNER_STRAIGHT_CUT
void BM_mesh_esubdivide(BMesh *bm, char edge_hflag, float smooth, short smooth_falloff, bool use_smooth_even, float fractal, float along_normal, int numcuts, int seltype, int cornertype, short use_single_edge, short use_grid_fill, short use_only_quads, int seed)
@ SUBD_RING_INTERP_LINEAR
@ BMOP_POKE_MEDIAN_WEIGHTED
void BM_vert_normal_update(BMVert *v)
bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3])
float BM_face_calc_area(const BMFace *f)
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
int BM_mesh_calc_edge_groups_as_arrays(BMesh *bm, BMVert **verts, BMEdge **edges, BMFace **faces, int(**r_groups)[3])
bool BM_vert_is_wire(const BMVert *v)
BMFace * BM_edge_pair_share_face_by_len(BMEdge *e_a, BMEdge *e_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
BMLoop * BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback)
BMESH EDGE/FACE ANGLE.
float BM_loop_calc_face_angle(const BMLoop *l)
BMLoop * BM_face_edge_share_loop(BMFace *f, BMEdge *e)
Return the Loop Shared by Face and Edge.
BMLoop * BM_face_vert_share_loop(BMFace *f, BMVert *v)
Return the Loop Shared by Face and Vertex.
bool BM_vert_pair_share_face_check_cb(BMVert *v_a, BMVert *v_b, bool(*test_fn)(BMFace *, void *user_data), void *user_data)
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
btMatrix3x3 absolute() const
Return the matrix with all values non negative.
static unsigned long seed
static AttributeOwner from_id(ID *id)
IndexRange index_range() const
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt,...)
bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt,...)
bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_slot_out, const bool select_extend, const char *fmt,...)
bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
BLI_INLINE float fb(float length, float L)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
void MESH_OT_convex_hull(wmOperatorType *ot)
static void clear(Message &msg)
bool shape_key_report_if_locked(const Object *obedit, ReportList *reports)
bool shape_key_report_if_any_locked(Object *ob, ReportList *reports)
void base_select(Base *base, eObjectSelect_Mode mode)
Base * add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, eDupli_ID_Flags dupflag)
bool calc_active_center_for_editmode(Object *obedit, bool select_only, float r_center[3])
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_int_get(PointerRNA *ptr, const char *name)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
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)
const char * RNA_property_identifier(const PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
PropertyRNA * RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_float_default(PropertyRNA *prop, float value)
void RNA_def_property_enum_default(PropertyRNA *prop, int value)
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
PropertyRNA * RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *identifier, const int len, 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_float_distance(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_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_enum_items(PropertyRNA *prop, const EnumPropertyItem *item)
PropertyRNA * RNA_def_float_vector_xyz(StructOrFunctionRNA *cont_, const char *identifier, const int len, 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_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
PropertyRNA * RNA_def_enum_flag(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_enum_items_add_value(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item, int value)
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)
const EnumPropertyItem rna_enum_mesh_delimit_mode_items[]
const EnumPropertyItem rna_enum_modifier_triangulate_ngon_method_items[]
const EnumPropertyItem rna_enum_axis_xyz_items[]
const EnumPropertyItem rna_enum_modifier_triangulate_quad_method_items[]
const EnumPropertyItem rna_enum_dummy_NULL_items[]
const EnumPropertyItem rna_enum_proportional_falloff_curve_only_items[]
const EnumPropertyItem rna_enum_symmetrize_direction_items[]
struct BMEditSelection * next
BMLoopNorEditData ** lidx_to_lnor_editdata
BMLoopNorEditData * lnor_editdata
int cd_custom_normal_offset
struct BMLoop * radial_next
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
bool update_shapekey_indices
struct MLoopNorSpaceArray * lnor_spacearr
float profile_shape_factor
MLoopNorSpace ** lspacearr
MeshRuntimeHandle * runtime
ObjectRuntimeHandle * runtime
bool(* poll_property)(const bContext *C, wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
bool(* check)(bContext *C, wmOperator *op)
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
void(* ui)(bContext *C, wmOperator *op)
void(* cancel)(bContext *C, wmOperator *op)
struct ReportList * reports
struct wmOperatorType * type
void WM_cursor_wait(bool val)
bool WM_operator_poll(bContext *C, wmOperatorType *ot)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
#define ISMOUSE_MOTION(event_type)
std::optional< std::string > WM_modalkeymap_operator_items_to_string(wmOperatorType *ot, const int propvalue, const bool compact)
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
const char * WM_bool_as_string(bool test)
void WM_operatortype_props_advanced_begin(wmOperatorType *ot)
void WM_operator_type_modal_from_exec_for_object_edit_coords(wmOperatorType *ot)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)