10#include <fmt/format.h>
59#include "RNA_prototypes.hh"
83#define USE_FACE_CREATE_SEL_EXTEND
108 for (
Object *obedit : objects) {
131 params.calc_looptris =
true;
132 params.calc_normals =
false;
133 params.is_destructive =
true;
146 {0,
nullptr, 0,
nullptr,
nullptr},
154 ot->name =
"Subdivide";
155 ot->description =
"Subdivide selected edges";
156 ot->idname =
"MESH_OT_subdivide";
166 prop =
RNA_def_int(
ot->srna,
"number_cuts", 1, 1, 100,
"Number of Cuts",
"", 1, 10);
172 ot->srna,
"smoothness", 0.0f, 0.0f, 1e3f,
"Smoothness",
"Smoothness factor", 0.0f, 1.0f);
180 "When disabled, newly created faces are limited to 3 and 4 sided faces");
187 "How to subdivide quad corners (anything other than Straight Cut will prevent n-gons)");
195 "Fractal randomness factor",
199 "fractal_along_normal",
204 "Apply fractal displacement along normal only",
213 "Seed for the random number generator",
238 const int cuts_default)
245 {0,
nullptr, 0,
nullptr,
nullptr},
251 ot->srna,
"number_cuts", cuts_default, 0, 1000,
"Number of Cuts",
"", cuts_min, 64);
256 prop_subd_edgering_types,
259 "Interpolation method");
262 ot->srna,
"smoothness", 1.0f, 0.0f, 1e3f,
"Smoothness",
"Smoothness factor", 0.0f, 2.0f);
266 "profile_shape_factor",
271 "How much intermediary new edges are shrunk/expanded",
303 for (
Object *obedit : objects) {
312 "subdivide_edgering edges=%he interp_mode=%i cuts=%i smooth=%f "
313 "profile_shape=%i profile_shape_factor=%f",
325 params.calc_looptris =
true;
326 params.calc_normals =
false;
327 params.is_destructive =
true;
337 ot->name =
"Subdivide Edge-Ring";
338 ot->description =
"Subdivide perpendicular edges to the selected edge-ring";
339 ot->idname =
"MESH_OT_subdivide_edgering";
365 for (
Object *obedit : objects) {
387 params.calc_looptris =
true;
388 params.calc_normals =
false;
389 params.is_destructive =
true;
399 ot->name =
"Un-Subdivide";
400 ot->description =
"Un-subdivide selected edges and faces";
401 ot->idname =
"MESH_OT_unsubdivide";
412 ot->srna,
"iterations", 2, 1, 1000,
"Iterations",
"Number of times to un-subdivide", 1, 100);
431 const int totelem_old[3],
432 const int totelem_new[3])
436 "Removed: %d vertices, %d edges, %d faces",
437 totelem_old[0] - totelem_new[0],
438 totelem_old[1] - totelem_new[1],
439 totelem_old[2] - totelem_new[2]);
449 bool changed_multi =
false;
451 for (
Object *obedit : objects) {
507 changed_multi =
true;
514 params.calc_looptris =
true;
515 params.calc_normals =
false;
516 params.is_destructive =
true;
534 {0,
nullptr, 0,
nullptr,
nullptr},
539 ot->description =
"Delete selected vertices, edges or faces";
540 ot->idname =
"MESH_OT_delete";
554 prop_mesh_delete_types,
557 "Method used for deleting mesh data");
576 }
while ((l_iter = l_iter->
next) != l_first);
585 int totelem_old_sel[3];
597 for (
Object *obedit : objects) {
644 params.calc_looptris =
true;
645 params.calc_normals =
false;
646 params.is_destructive =
true;
661 ot->name =
"Delete Loose";
662 ot->description =
"Delete loose vertices, edges or faces";
663 ot->idname =
"MESH_OT_delete_loose";
674 RNA_def_boolean(
ot->srna,
"use_verts",
true,
"Vertices",
"Remove loose vertices");
691 for (
Object *obedit : objects) {
703 params.calc_looptris =
true;
704 params.calc_normals =
false;
705 params.is_destructive =
true;
715 ot->name =
"Collapse Edges & Faces";
717 "Collapse isolated edge and face regions, merging data such as UVs and color attributes. "
718 "This can collapse edge-rings as well as regions of connected faces into vertices";
719 ot->idname =
"MESH_OT_edge_collapse";
740 uint vote_on_smooth[2] = {0, 0};
748 return (vote_on_smooth[0] < vote_on_smooth[1]);
751#ifdef USE_FACE_CREATE_SEL_EXTEND
764 if ((e_used ==
nullptr) || (e_used != e_iter)) {
767 if (
i >= e_arr_len) {
782 if (
bm->totvertsel == 1 &&
bm->totedgesel == 0 &&
bm->totfacesel == 0) {
814 else if (
bm->totvertsel == 2 &&
bm->totedgesel == 1 &&
bm->totfacesel == 0) {
900 BMEdge *e_active =
l->next->next->e;
906 BMVert *v_active =
l->next->next->v;
918 bool changed_multi =
false;
923 for (
Object *obedit : objects) {
935#ifdef USE_FACE_CREATE_SEL_EXTEND
946 "contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
961#ifdef USE_FACE_CREATE_SEL_EXTEND
965 (ele_desel_face =
static_cast<BMFace *
>(
995 params.calc_looptris =
true;
996 params.calc_normals =
false;
997 params.is_destructive =
true;
999 changed_multi =
true;
1002 if (!changed_multi) {
1012 ot->name =
"Make Edge/Face";
1013 ot->description =
"Add an edge or face to selected";
1014 ot->idname =
"MESH_OT_edge_face_add";
1040 for (
Object *obedit : objects) {
1044 if (
bm->totedgesel == 0) {
1069 for (
Object *obedit : objects) {
1071 params.calc_looptris =
true;
1072 params.calc_normals =
false;
1073 params.is_destructive =
false;
1085 ot->name =
"Mark Seam";
1086 ot->idname =
"MESH_OT_mark_seam";
1087 ot->description =
"(Un)mark selected edges as a seam";
1119 for (
Object *obedit : objects) {
1123 if ((use_verts &&
bm->totvertsel == 0) || (!use_verts &&
bm->totedgesel == 0)) {
1143 params.calc_looptris =
true;
1144 params.calc_normals =
false;
1145 params.is_destructive =
false;
1157 ot->name =
"Mark Sharp";
1158 ot->idname =
"MESH_OT_mark_sharp";
1159 ot->description =
"(Un)mark selected edges as sharp";
1175 "Consider vertices instead of edges to select which edges to (un)tag as sharp");
1189 const int verts_len =
bm->totvertsel;
1190 bool is_pair = (verts_len == 2);
1192 bool check_degenerate =
true;
1194 bool checks_succeded =
true;
1197 if (verts_len < 2) {
1216 check_degenerate =
false;
1225 "connect_vert_pair verts=%eb verts_exclude=%hv faces_exclude=%hf",
1231 checks_succeded =
false;
1238 "connect_verts verts=%eb faces_exclude=%hf check_degenerate=%b",
1244 checks_succeded =
false;
1247 if (checks_succeded) {
1256 if (
len && is_pair) {
1262 bool em_backup_free =
true;
1269 em_backup_free =
false;
1278 params.calc_looptris =
true;
1279 params.calc_normals =
false;
1280 params.is_destructive =
true;
1284 if (em_backup_free) {
1297 uint failed_objects_len = 0;
1301 for (
Object *obedit : objects) {
1305 failed_objects_len++;
1314 ot->name =
"Vertex Connect";
1315 ot->idname =
"MESH_OT_vert_connect";
1316 ot->description =
"Connect selected vertices of faces, splitting the face";
1356 const int totedge_orig =
bm->totedge;
1370 return (
bm->totedge != totedge_orig);
1384 bool changed =
false;
1385 bool has_wire =
false;
1401 if (has_wire ==
false) {
1403 if (tot ==
bm->totvertsel) {
1406 ese = ese_last->
next;
1416 }
while ((
void)(ese_last = ese), (ese = ese->
next));
1423 if (changed ==
false) {
1441 ese = ese_prev->
next;
1454 }
while ((
void)(ese_prev = ese), (ese = ese->
next));
1456 if (changed ==
false) {
1481 ListBase selected_orig = {
nullptr,
nullptr};
1495 if (
bm->totedgesel != edges_len) {
1499 std::swap(
bm->selected, selected_orig);
1504 BMEdge *e_prev = ese->prev ? (
BMEdge *)ese->prev->ele :
nullptr;
1512 if ((e_curr->
v1 != l_curr->
v) == (e_prev->
v1 != l_prev->
v)) {
1521 v = (&e_curr->
v1)[side];
1526 v = (&e_curr->
v1)[!side];
1534 *r_selected =
bm->selected;
1535 bm->selected = selected_orig;
1544 uint failed_selection_order_len = 0;
1545 uint failed_connect_len = 0;
1546 bool has_select_history_mixed =
false;
1547 bool has_select_history_face =
false;
1551 for (
Object *obedit : objects) {
1555 ListBase selected_orig = {
nullptr,
nullptr};
1557 if (
bm->totvertsel == 0) {
1564 failed_connect_len++;
1572 has_select_history_mixed =
true;
1573 failed_selection_order_len++;
1577 if (htype_selected &
BM_FACE) {
1578 has_select_history_face =
true;
1579 failed_selection_order_len++;
1583 if (
bm->selected.first) {
1587 std::swap(
bm->selected, selected_orig);
1600 params.calc_looptris =
true;
1601 params.calc_normals =
false;
1602 params.is_destructive =
true;
1606 failed_selection_order_len++;
1611 bm->selected = selected_orig;
1615 if (failed_selection_order_len == objects.
size()) {
1616 if (has_select_history_mixed) {
1619 else if (has_select_history_face) {
1627 if (failed_connect_len == objects.
size()) {
1638 ot->name =
"Vertex Connect Path";
1639 ot->idname =
"MESH_OT_vert_connect_path";
1640 ot->description =
"Connect vertices by their selection order, creating edges, splitting faces";
1662 for (
Object *obedit : objects) {
1670 em, op,
"faces.out",
true,
"connect_verts_concave faces=%hf",
BM_ELEM_SELECT))
1675 params.calc_looptris =
true;
1676 params.calc_normals =
false;
1677 params.is_destructive =
true;
1687 ot->name =
"Split Concave Faces";
1688 ot->idname =
"MESH_OT_vert_connect_concave";
1689 ot->description =
"Make all faces convex";
1713 for (
Object *obedit : objects) {
1724 "connect_verts_nonplanar faces=%hf angle_limit=%f",
1732 params.calc_looptris =
true;
1733 params.calc_normals =
false;
1734 params.is_destructive =
true;
1746 ot->name =
"Split Non-Planar Faces";
1747 ot->idname =
"MESH_OT_vert_connect_nonplanar";
1748 ot->description =
"Split non-planar faces that exceed the angle threshold";
1789 for (
Object *obedit : objects) {
1803 em, op,
"planar_faces faces=%hf iterations=%i factor=%f",
BM_ELEM_SELECT, repeat, fac))
1809 params.calc_looptris =
true;
1810 params.calc_normals =
true;
1811 params.is_destructive =
true;
1821 ot->name =
"Make Planar Faces";
1822 ot->idname =
"MESH_OT_face_make_planar";
1823 ot->description =
"Flatten selected faces";
1833 RNA_def_float(
ot->srna,
"factor", 1.0f, -10.0f, 10.0f,
"Factor",
"", 0.0f, 1.0f);
1834 RNA_def_int(
ot->srna,
"repeat", 1, 1, 10000,
"Iterations",
"", 1, 200);
1846 if (
bm->totedgesel == 0) {
1853 em, op,
"edges.out",
false,
"split_edges edges=%he",
BM_ELEM_SELECT))
1862 params.calc_looptris =
true;
1863 params.calc_normals =
false;
1864 params.is_destructive =
true;
1876 if (
bm->totvertsel == 0) {
1887 if (eed->
l !=
nullptr) {
1903 "split_edges edges=%he verts=%hv use_verts=%b",
1912 if (eed->
l !=
nullptr) {
1922 for (
int i = 0;
i < 2;
i++) {
1937 params.calc_looptris =
true;
1938 params.calc_normals =
false;
1939 params.is_destructive =
true;
1953 for (
Object *obedit : objects) {
1978 ot->name =
"Edge Split";
1979 ot->idname =
"MESH_OT_edge_split";
1980 ot->description =
"Split selected edges so that each neighbor face gets its own copy";
1991 {
BM_EDGE,
"EDGE", 0,
"Faces by Edges",
"Split faces along selected edges"},
1995 "Faces & Edges by Vertices",
1996 "Split faces and edges connected to selected vertices"},
1997 {0,
nullptr, 0,
nullptr,
nullptr},
2001 ot->srna,
"type", split_type_items,
BM_EDGE,
"Type",
"Method to use for splitting");
2016 bool changed =
false;
2018 for (
Object *obedit : objects) {
2031 "duplicate geom=%hvef use_select_history=%b use_edge_flip_from_face=%b",
2053 params.calc_looptris =
true;
2054 params.calc_normals =
false;
2055 params.is_destructive =
true;
2076 ot->name =
"Duplicate";
2077 ot->description =
"Duplicate selected vertices, edges or faces";
2078 ot->idname =
"MESH_OT_duplicate";
2114 return lnors_ed_arr;
2119 if (!lnors_ed_arr) {
2123 if (lnors_ed_arr->
totloop == 0) {
2144 for (
int i = 0;
i < lnors_ed_arr_new_full->
totloop;
i++, lnor_ed_new_full++) {
2152 bm->lnor_spacearr->lspacearr[lnor_ed_new_full->
loop_index],
2180 BLI_assert(lnor_ed !=
nullptr && lnor_ed_new !=
nullptr);
2185 bm->lnor_spacearr->lspacearr[loop_index], lnor_ed->
nloc, lnor_ed_new->
clnors_data);
2189 }
while (
l != l_start);
2214 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
2222 params.calc_looptris =
true;
2223 params.calc_normals =
false;
2224 params.is_destructive =
false;
2232 params.calc_looptris =
true;
2233 params.calc_normals =
false;
2234 params.is_destructive =
false;
2242 bool has_flipped_faces =
false;
2248 has_flipped_faces =
true;
2253 params.calc_looptris =
true;
2254 params.calc_normals =
false;
2255 params.is_destructive =
false;
2259 if (lnors_ed_arr !=
nullptr) {
2271 for (
Object *obedit : objects) {
2291 for (
Object *obedit : objects) {
2314 ot->name =
"Flip Normals";
2315 ot->description =
"Flip the direction of selected faces' normals (and of their vertices)";
2316 ot->idname =
"MESH_OT_flip_normals";
2328 "Custom Normals Only",
2329 "Only flip the custom loop normals of the selected elements");
2347 int tot_failed_all = 0;
2348 bool no_selected_edges =
true, invalid_selected_edges =
true;
2354 for (
Object *obedit : objects) {
2361 no_selected_edges =
false;
2384 invalid_selected_edges =
false;
2402 const int tot_failed = tot - tot_rotate;
2404 tot_failed_all += tot_failed;
2406 if (tot_failed != 0) {
2420 params.calc_looptris =
true;
2421 params.calc_normals =
false;
2422 params.is_destructive =
true;
2426 if (no_selected_edges) {
2428 op->
reports,
RPT_ERROR,
"Select edges or face pairs for edge loops to rotate about");
2434 if (invalid_selected_edges) {
2439 if (tot_failed_all != 0) {
2449 ot->name =
"Rotate Selected Edge";
2450 ot->description =
"Rotate selected edge or adjoining faces";
2451 ot->idname =
"MESH_OT_edge_rotate";
2475 bool changed =
false;
2479 for (
Object *obedit : objects) {
2485 if (
bm->totvertsel ==
bm->totvert) {
2490 if (
bm->totedgesel ==
bm->totedge) {
2495 if (
bm->totfacesel ==
bm->totface) {
2501 if (
bm->totvertsel == 0) {
2516 params.calc_looptris =
true;
2517 params.calc_normals =
false;
2518 params.is_destructive =
false;
2534 ot->name =
"Hide Selected";
2535 ot->idname =
"MESH_OT_hide";
2536 ot->description =
"Hide (un)selected vertices, edges or faces";
2547 ot->srna,
"unselected",
false,
"Unselected",
"Hide unselected rather than selected");
2564 for (
Object *obedit : objects) {
2569 params.calc_looptris =
true;
2570 params.calc_normals =
false;
2571 params.is_destructive =
false;
2582 ot->name =
"Reveal Hidden";
2583 ot->idname =
"MESH_OT_reveal";
2584 ot->description =
"Reveal all hidden vertices, edges and faces";
2610 for (
Object *obedit : objects) {
2631 if (lnors_ed_arr !=
nullptr) {
2637 params.calc_looptris =
true;
2638 params.calc_normals =
false;
2639 params.is_destructive =
false;
2649 ot->name =
"Recalculate Normals";
2650 ot->description =
"Make face and vertex normals point either outside or inside the mesh";
2651 ot->idname =
"MESH_OT_normals_make_consistent";
2684 int tot_selected = 0, tot_locked = 0;
2687 for (
Object *obedit : objects) {
2688 Mesh *mesh =
static_cast<Mesh *
>(obedit->data);
2690 bool mirrx =
false, mirry =
false, mirrz =
false;
2691 float clip_dist = 0.0f;
2733 for (
int i = 0;
i < repeat;
i++) {
2737 "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b "
2738 "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b",
2754 bool calc_normals =
false;
2760 calc_normals =
true;
2764 params.calc_looptris =
true;
2765 params.calc_normals = calc_normals;
2766 params.is_destructive =
false;
2770 if (tot_selected == 0 && !tot_locked) {
2780 ot->name =
"Smooth Vertices";
2781 ot->description =
"Flatten angles of selected vertices";
2782 ot->idname =
"MESH_OT_vertices_smooth";
2792 ot->srna,
"factor", 0.0f, -10.0f, 10.0f,
"Smoothing",
"Smoothing factor", 0.0f, 1.0f);
2794 ot->srna,
"repeat", 1, 1, 1000,
"Repeat",
"Number of times to smooth the mesh", 1, 100);
2814 int tot_selected = 0, tot_locked = 0;
2832 for (
Object *obedit : objects) {
2834 Mesh *mesh =
static_cast<Mesh *
>(obedit->data);
2853 bool failed_repeat_loop =
false;
2854 for (
int i = 0;
i < repeat;
i++) {
2857 "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f "
2858 "use_x=%b use_y=%b use_z=%b preserve_volume=%b",
2867 failed_repeat_loop =
true;
2871 if (failed_repeat_loop) {
2876 bool calc_normals =
false;
2882 calc_normals =
true;
2886 params.calc_looptris =
true;
2887 params.calc_normals = calc_normals;
2888 params.is_destructive =
false;
2892 if (tot_selected == 0 && !tot_locked) {
2902 ot->name =
"Laplacian Smooth Vertices";
2903 ot->description =
"Laplacian smooth of selected vertices";
2904 ot->idname =
"MESH_OT_vertices_smooth_laplacian";
2914 ot->srna,
"repeat", 1, 1, 1000,
"Number of iterations to smooth the mesh",
"", 1, 200);
2916 ot->srna,
"lambda_factor", 1.0f, 1e-7f, 1000.0f,
"Lambda factor",
"", 1e-7f, 1000.0f);
2922 "Lambda factor in border",
2929 RNA_def_boolean(
ot->srna,
"use_x",
true,
"Smooth X Axis",
"Smooth object along X axis");
2930 RNA_def_boolean(
ot->srna,
"use_y",
true,
"Smooth Y Axis",
"Smooth object along Y axis");
2931 RNA_def_boolean(
ot->srna,
"use_z",
true,
"Smooth Z Axis",
"Smooth object along Z axis");
2936 "Apply volume preservation after smooth");
2950 if (em ==
nullptr) {
2967 for (
Object *obedit : objects) {
2976 params.calc_looptris =
false;
2977 params.calc_normals =
false;
2978 params.is_destructive =
false;
2988 ot->name =
"Shade Smooth";
2989 ot->description =
"Display faces smooth (using vertex normals)";
2990 ot->idname =
"MESH_OT_faces_shade_smooth";
3012 for (
Object *obedit : objects) {
3021 params.calc_looptris =
false;
3022 params.calc_normals =
false;
3023 params.is_destructive =
false;
3033 ot->name =
"Shade Flat";
3034 ot->description =
"Display faces flat";
3035 ot->idname =
"MESH_OT_faces_shade_flat";
3060 for (
Object *obedit : objects) {
3078 params.calc_looptris =
false;
3079 params.calc_normals =
false;
3080 params.is_destructive =
false;
3093 for (
Object *obedit : objects) {
3110 params.calc_looptris =
false;
3111 params.calc_normals =
false;
3112 params.is_destructive =
false;
3129 for (
uint ob_index = 0; ob_index < objects.
size(); ob_index++) {
3130 Object *ob = objects[ob_index];
3151 "rotate_colors faces=%hf use_ccw=%b color_index=%i",
3164 params.calc_looptris =
false;
3165 params.calc_normals =
false;
3166 params.is_destructive =
false;
3180 for (
Object *obedit : objects) {
3200 em, &bmop, op,
"reverse_colors faces=%hf color_index=%i",
BM_ELEM_SELECT, color_index);
3209 params.calc_looptris =
false;
3210 params.calc_normals =
false;
3211 params.is_destructive =
false;
3221 ot->name =
"Rotate UVs";
3222 ot->idname =
"MESH_OT_uvs_rotate";
3223 ot->description =
"Rotate UV coordinates inside faces";
3239 ot->name =
"Reverse UVs";
3240 ot->idname =
"MESH_OT_uvs_reverse";
3241 ot->description =
"Flip direction of UV coordinates inside faces";
3257 ot->name =
"Rotate Colors";
3258 ot->idname =
"MESH_OT_colors_rotate";
3259 ot->description =
"Rotate face corner color attribute inside faces";
3275 ot->name =
"Reverse Colors";
3276 ot->idname =
"MESH_OT_colors_reverse";
3277 ot->description =
"Flip direction of face corner color attribute inside faces";
3288 RNA_def_enum(
ot->srna,
"axis", axis_items, DIRECTION_CW,
"Axis",
"Axis to mirror colors around");
3307 const bool use_first,
3308 const bool use_uvmerge,
3320 if (use_first ==
false) {
3343 em, wmop,
"pointmerge_facedata verts=%hv vert_snap=%e",
BM_ELEM_SELECT, mergevert))
3360 const bool use_cursor,
3361 const bool use_uvmerge,
3366 float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
3367 const float *vco =
nullptr;
3373 mul_m4_v3(ob->world_to_object().ptr(), co);
3422 for (
Object *obedit : objects) {
3460 params.calc_looptris =
true;
3461 params.calc_normals =
false;
3462 params.is_destructive =
true;
3484 {0,
nullptr, 0,
nullptr,
nullptr},
3546 ot->description =
"Merge selected vertices";
3547 ot->idname =
"MESH_OT_merge";
3577 const bool use_sharp_edge_from_normals =
RNA_boolean_get(op->
ptr,
"use_sharp_edge_from_normals");
3579 int count_multi = 0;
3586 for (
Object *obedit : objects) {
3595 const int totvert_orig = em->
bm->
totvert;
3614 if (use_unselected) {
3624 "weld_verts targetmap=%S use_centroid=%b",
3647 count_multi +=
count;
3649 params.calc_looptris =
true;
3650 params.calc_normals =
false;
3651 params.is_destructive =
true;
3658 count_multi == 1 ?
RPT_(
"Removed %d vertex") :
RPT_(
"Removed %d vertices"),
3667 ot->name =
"Merge by Distance";
3668 ot->description =
"Merge vertices based on their proximity";
3669 ot->idname =
"MESH_OT_remove_doubles";
3684 "Maximum distance between elements to merge",
3691 "Move vertices to the centroid of the duplicate cluster, "
3692 "otherwise the vertex closest to the centroid is used.");
3698 "Merge selected to other unselected vertices");
3701 "use_sharp_edge_from_normals",
3704 "Calculate sharp edges using custom normal data (when available)");
3736 for (
int i = 0;
i < totshape;
i++) {
3737 co =
static_cast<float *
>(
3749 int tot_shapekeys = 0;
3750 int tot_selected_verts_objects = 0;
3755 for (
Object *obedit : objects) {
3756 Mesh *mesh =
static_cast<Mesh *
>(obedit->data);
3769 tot_selected_verts_objects++;
3788 params.calc_looptris =
false;
3789 params.calc_normals =
false;
3790 params.is_destructive =
false;
3794 if (tot_selected_verts_objects == 0) {
3800 if (tot_shapekeys == 0) {
3811 ot->name =
"Shape Propagate";
3812 ot->description =
"Apply selected vertex locations to all other shape keys";
3813 ot->idname =
"MESH_OT_shape_propagate_to_all";
3834 Key *key_ref = me_ref->
key;
3842 int totshape_ref = 0;
3851 if (totshape_ref == 0 || shape_ref < 0) {
3855 if (shape_ref >= totshape_ref) {
3865 int tot_selected_verts_objects = 0, tot_locked = 0;
3868 for (
Object *obedit : objects) {
3869 Mesh *mesh =
static_cast<Mesh *
>(obedit->data);
3884 tot_selected_verts_objects++;
3908 sco =
static_cast<float *
>(
3914 const float *rco =
static_cast<const float *
>(
3932 params.calc_looptris =
true;
3933 params.calc_normals =
true;
3934 params.is_destructive =
false;
3939 if (tot_selected_verts_objects == 0 && !tot_locked) {
3967 tmp.
value = totitem;
3992 layout->
prop_search(op->
ptr,
"shape", &ptr_key,
"key_blocks", std::nullopt, ICON_SHAPEKEY_DATA);
4002 ot->name =
"Blend from Shape";
4003 ot->description =
"Blend in shape from a shape key";
4004 ot->idname =
"MESH_OT_blend_from_shape";
4021 RNA_def_float(
ot->srna,
"blend", 1.0f, -1e3f, 1e3f,
"Blend",
"Blending factor", -2.0f, 2.0f);
4022 RNA_def_boolean(
ot->srna,
"add",
true,
"Add",
"Add rather than blend between shapes");
4039 for (
Object *obedit : objects) {
4073 params.calc_looptris =
true;
4074 params.calc_normals =
false;
4075 params.is_destructive =
true;
4086 ot->name =
"Solidify";
4087 ot->description =
"Create a solid skin by extruding, compensating for sharp angles";
4088 ot->idname =
"MESH_OT_solidify";
4098 ot->srna,
"thickness", 0.01f, -1e4f, 1e4f,
"Thickness",
"", -10.0f, 10.0f);
4144 "duplicate geom=%hvef dest=%p",
4149 "delete geom=%hvef context=%i",
4182 bm_new_allocsize.
totvert = verts_len;
4183 bm_new_allocsize.
totedge = edges_len;
4184 bm_new_allocsize.
totloop = faces_len * 3;
4185 bm_new_allocsize.
totface = faces_len;
4187 const bool use_custom_normals = (bm_old->
lnor_spacearr !=
nullptr);
4194 if (use_custom_normals) {
4220 if (use_custom_normals) {
4224 for (
uint i = 0;
i < verts_len;
i++) {
4257 ID *obdata =
static_cast<ID *
>(ob->
data);
4262 if ((totcolp && matarar) == 0) {
4272 if (mat_nr < ob->totcol) {
4273 ma_ob = ob->
mat[mat_nr];
4281 if (mat_nr < *totcolp) {
4282 ma_obdata = (*matarar)[mat_nr];
4285 ma_obdata =
nullptr;
4295 (*matarar)[0] = ma_obdata;
4312 const short mat_nr = f_cmp->
mat_nr;
4318 if (f->
mat_nr == mat_nr) {
4327 }
while ((l_iter = l_iter->
next) != l_first);
4350 result |= (base_new !=
nullptr);
4362 const bool clear_object_data =
true;
4370 int (*groups)[3] =
nullptr;
4372 bm_old, vert_groups.
data(), edge_groups.
data(), face_groups.
data(), &groups);
4373 if (groups_len <= 1) {
4378 if (clear_object_data) {
4385 uint group_ofs[3] = {
uint(groups[0][0]),
uint(groups[0][1]),
uint(groups[0][2])};
4386 for (
int i = 1;
i < groups_len;
i++) {
4392 vert_groups.
data() + group_ofs[0],
4394 edge_groups.
data() + group_ofs[1],
4396 face_groups.
data() + group_ofs[2],
4398 result |= (base_new !=
nullptr);
4400 group_ofs[0] += groups[
i][0];
4401 group_ofs[1] += groups[
i][1];
4402 group_ofs[2] += groups[
i][2];
4408 if (clear_object_data) {
4424 bool changed_multi =
false;
4427 uint empty_selection_len = 0;
4430 for (
const int base_index : bases.
index_range()) {
4431 Base *base = bases[base_index];
4437 if (++empty_selection_len == bases.
size()) {
4445 bool changed =
false;
4463 params.calc_looptris =
true;
4464 params.calc_normals =
false;
4465 params.is_destructive =
true;
4468 changed_multi |= changed;
4479 Object *ob = base_iter->object;
4495 bool changed =
false;
4519 changed_multi |= changed;
4524 if (changed_multi) {
4542 {0,
nullptr, 0,
nullptr,
nullptr},
4546 ot->name =
"Separate";
4547 ot->description =
"Separate selected geometry into a new mesh";
4548 ot->idname =
"MESH_OT_separate";
4572 bool has_selected_edges =
false, has_faces_filled =
false;
4578 for (
Object *obedit : objects) {
4581 const int totface_orig = em->
bm->
totface;
4586 has_selected_edges =
true;
4590 em, &bmop, op,
"triangle_fill edges=%he use_beauty=%b",
BM_ELEM_SELECT, use_beauty))
4602 has_faces_filled =
true;
4613 params.calc_looptris =
true;
4614 params.calc_normals =
false;
4615 params.is_destructive =
true;
4619 if (!has_selected_edges) {
4624 if (!has_faces_filled) {
4636 ot->idname =
"MESH_OT_fill";
4637 ot->description =
"Fill a selected edge loop with faces";
4647 RNA_def_boolean(
ot->srna,
"use_beauty",
true,
"Beauty",
"Use best triangulation division");
4684 const float eps_even = 1e-3f;
4712 for (
int i = 0;
i < edges_len;
i++) {
4717 span = verts_len / 4;
4720 span =
min_ii(span, (verts_len / 2) - 1);
4722 offset =
mod_i(offset, verts_len);
4724 if ((
count == 1) && ((verts_len & 1) == 0) && (verts_len == edges_len)) {
4732 if (v_act && (v_act_link =
static_cast<LinkData *
>(
4740 float angle_best = -1.0f;
4743 if ((
angle > angle_best) || (v_link_best ==
nullptr)) {
4745 v_link_best = v_link;
4749 v_act_link = v_link_best;
4750 v_act =
static_cast<BMVert *
>(v_act_link->
data);
4758 v_act =
static_cast<BMVert *
>(v_act_link->
data);
4775 for (v_link =
static_cast<LinkData *
>(
verts->first),
i = 0; v_link;
4776 v_link = v_link->
next,
i++)
4781 ele_sort[
i].
data = v_link;
4784 if (
ELEM(
i, 0, verts_len / 2)) {
4796 if ((ele_sort[0].sort_value - ele_sort[verts_len - 3].sort_value) > eps_even) {
4808 if (span > verts_len / 2) {
4809 span = (verts_len)-span;
4810 start = (verts_len / 2) - span;
4814 for (
i = start;
i < start + span;
i++) {
4965 for (
uint ob_index = 0; ob_index < objects.
size(); ob_index++) {
4967 Object *obedit = objects[ob_index];
4973 bool use_prepare =
true;
4981 const int totedge_orig = em->
bm->
totedge;
4982 const int totface_orig = em->
bm->
totface;
5021 "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b",
5028 const bool has_geometry_changed = totedge_orig != em->
bm->
totedge ||
5039 if (changed || split_join) {
5041 params.calc_looptris =
true;
5042 params.calc_normals =
false;
5043 params.is_destructive =
true;
5062 ot->name =
"Grid Fill";
5063 ot->description =
"Fill grid from two loops";
5064 ot->idname =
"MESH_OT_fill_grid";
5074 prop =
RNA_def_int(
ot->srna,
"span", 1, 1, 1000,
"Span",
"Number of grid columns", 1, 100);
5082 "Vertex that is the corner of the grid",
5087 "use_interp_simple",
5090 "Use simple interpolation of grid vertices");
5108 for (
Object *obedit : objects) {
5116 em, op,
"faces.out",
true,
"holes_fill edges=%he sides=%i",
BM_ELEM_SELECT, sides))
5122 params.calc_looptris =
true;
5123 params.calc_normals =
false;
5124 params.is_destructive =
true;
5134 ot->name =
"Fill Holes";
5135 ot->idname =
"MESH_OT_fill_holes";
5136 ot->description =
"Fill in holes (boundary edge loops)";
5151 "Number of sides in hole required to fill (zero fills all holes)",
5169 const float angle_max =
M_PI;
5173 for (
Object *obedit : objects) {
5180 if (angle_limit >= angle_max) {
5197 em, op,
"geom.out",
true,
"beautify_fill faces=%hf edges=%he",
BM_ELEM_SELECT, hflag))
5203 params.calc_looptris =
true;
5204 params.calc_normals =
false;
5205 params.is_destructive =
true;
5217 ot->name =
"Beautify Faces";
5218 ot->idname =
"MESH_OT_beautify_fill";
5219 ot->description =
"Rearrange some faces to try to get less degenerated geometry";
5258 for (
Object *obedit : objects) {
5269 "poke faces=%hf offset=%f use_relative_offset=%b center_mode=%i",
5272 use_relative_offset,
5288 params.calc_looptris =
true;
5289 params.calc_normals =
true;
5290 params.is_destructive =
true;
5304 "Weighted median face center"},
5307 {0,
nullptr, 0,
nullptr,
nullptr},
5311 ot->name =
"Poke Faces";
5312 ot->idname =
"MESH_OT_poke";
5313 ot->description =
"Split a face into a fan";
5323 ot->srna,
"offset", 0.0f, -1e3f, 1e3f,
"Poke Offset",
"Poke Offset", -1.0f, 1.0f);
5325 "use_relative_offset",
5328 "Scale the offset by surrounding geometry");
5334 "Poke face center calculation");
5352 for (
Object *obedit : objects) {
5368 "triangulate faces=%hf quad_method=%i ngon_method=%i",
5392 params.calc_looptris =
true;
5393 params.calc_normals =
false;
5394 params.is_destructive =
true;
5404 ot->name =
"Triangulate Faces";
5405 ot->idname =
"MESH_OT_quads_convert_to_tris";
5406 ot->description =
"Triangulate selected faces";
5420 "Method for splitting the quads into triangles");
5426 "Method for splitting the n-gons into triangles");
5436# define USE_JOIN_TRIANGLE_TESTING_API
5453#ifdef USE_JOIN_TRIANGLE_TESTING_API
5458 const float topology_influence =
RNA_float_get(op->
ptr,
"topology_influence");
5461 float angle_face_threshold, angle_shape_threshold;
5466 is_face_pair = (totelem_sel[2] == 2);
5475 angle_face_threshold =
DEG2RADF(180.0f);
5483 angle_shape_threshold =
DEG2RADF(180.0f);
5490 for (
Object *obedit : objects) {
5499 bool extend_selection = (deselect_joined ==
false);
5501#ifdef USE_JOIN_TRIANGLE_TESTING_API
5502 if (merge_limit != -1) {
5503 extend_selection =
false;
5512 "join_triangles faces=%hf angle_face_threshold=%f angle_shape_threshold=%f "
5513 "cmp_seam=%b cmp_sharp=%b cmp_uvs=%b cmp_vcols=%b cmp_materials=%b "
5514#ifdef USE_JOIN_TRIANGLE_TESTING_API
5515 "merge_limit=%i neighbor_debug=%i "
5517 "topology_influence=%f deselect_joined=%b",
5519 angle_face_threshold,
5520 angle_shape_threshold,
5526#ifdef USE_JOIN_TRIANGLE_TESTING_API
5536 if (deselect_joined) {
5548 params.calc_looptris =
true;
5549 params.calc_normals =
false;
5550 params.is_destructive =
true;
5561#ifdef USE_JOIN_TRIANGLE_TESTING_API
5568 "Maximum number of merges",
5579 "Neighbor to highlight",
5604 "Shape angle limit",
5610 "topology_influence",
5614 "Topology Influence",
5615 "How much to prioritize regular grids of quads as well as "
5616 "quads that touch existing quads",
5630 "Only select remaining triangles that were not merged");
5636 ot->name =
"Triangles to Quads";
5637 ot->idname =
"MESH_OT_tris_convert_to_quads";
5638 ot->description =
"Merge triangles into four sided polygons where possible";
5665 const float vertex_group_factor =
RNA_float_get(op->
ptr,
"vertex_group_factor");
5668 const float symmetry_eps = 0.00002f;
5669 const int symmetry_axis = use_symmetry ?
RNA_enum_get(op->
ptr,
"symmetry_axis") : -1;
5672 if (ratio == 1.0f) {
5681 for (
Object *obedit : objects) {
5684 if (
bm->totedgesel == 0) {
5693 if (use_vertex_group && (cd_dvert_offset == -1)) {
5695 use_vertex_group =
false;
5702 float weight = 0.0f;
5704 if (use_vertex_group) {
5708 if (invert_vertex_group) {
5709 weight = 1.0f - weight;
5717 vweights[
i] = weight;
5725 if ((
bm->totface ==
bm->totfacesel) || (ratio == 0.0f)) {
5726 ratio_adjust = ratio;
5737 int totface_basis = 0;
5738 int totface_adjacent = 0;
5743 const int f_len = f->
len > 4 ? (f->
len - 2) : 1;
5744 totface_basis += f_len;
5746 BMLoop *l_iter, *l_first;
5750 totface_adjacent += f_len;
5753 }
while ((l_iter = l_iter->
next) != l_first);
5756 ratio_adjust = ratio;
5757 ratio_adjust = 1.0f - ratio_adjust;
5758 ratio_adjust *=
float(totface_adjacent) /
float(totface_basis);
5759 ratio_adjust = 1.0f - ratio_adjust;
5763 em->
bm, ratio_adjust, vweights, vertex_group_factor,
false, symmetry_axis, symmetry_eps);
5777 params.calc_looptris =
true;
5778 params.calc_normals =
true;
5779 params.is_destructive =
true;
5805 row = &layout->
row(
true,
IFACE_(
"Symmetry"));
5807 sub = &row->row(
true);
5815 ot->name =
"Decimate Geometry";
5816 ot->idname =
"MESH_OT_decimate";
5817 ot->description =
"Simplify geometry by collapsing edges";
5829 RNA_def_float(
ot->srna,
"ratio", 1.0f, 0.0f, 1.0f,
"Ratio",
"", 0.0f, 1.0f);
5835 "Use active vertex group as an influence");
5837 "vertex_group_factor",
5842 "Vertex group strength",
5846 ot->srna,
"invert_vertex_group",
false,
"Invert",
"Invert vertex group influence");
5848 RNA_def_boolean(
ot->srna,
"use_symmetry",
false,
"Symmetry",
"Maintain symmetry on an axis");
5866 "Dissolve Vertices",
5867 "Dissolve remaining vertices which connect to only two edges");
5879 "Split off face corners to maintain surrounding geometry");
5884 "use_boundary_tear",
5887 "Split off face corners instead of merging faces");
5899 "Remaining vertices which separate edge pairs are preserved if their edge angle exceeds "
5919 for (
Object *obedit : objects) {
5930 "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
5941 params.calc_looptris =
true;
5942 params.calc_normals =
false;
5943 params.is_destructive =
true;
5953 ot->name =
"Dissolve Vertices";
5954 ot->description =
"Dissolve vertices, merge edges and faces";
5955 ot->idname =
"MESH_OT_dissolve_verts";
5984 for (
Object *obedit : objects) {
5996 "dissolve_edges edges=%he use_verts=%b use_face_split=%b angle_threshold=%f",
6008 params.calc_looptris =
true;
6009 params.calc_normals =
false;
6010 params.is_destructive =
true;
6020 ot->name =
"Dissolve Edges";
6021 ot->description =
"Dissolve edges, merging faces";
6022 ot->idname =
"MESH_OT_dissolve_edges";
6049 for (
Object *obedit : objects) {
6062 "dissolve_faces faces=%hf use_verts=%b",
6072 params.calc_looptris =
true;
6073 params.calc_normals =
false;
6074 params.is_destructive =
true;
6084 ot->name =
"Dissolve Faces";
6085 ot->description =
"Dissolve faces";
6086 ot->idname =
"MESH_OT_dissolve_faces";
6135 bool is_edge_select_mode =
false;
6141 is_edge_select_mode =
true;
6144 if (!is_edge_select_mode) {
6146 if (
STREQ(prop_id,
"angle_threshold")) {
6156 ot->name =
"Dissolve Selection";
6157 ot->description =
"Dissolve geometry based on the selection mode";
6158 ot->idname =
"MESH_OT_dissolve_mode";
6183 const bool use_dissolve_boundaries =
RNA_boolean_get(op->
ptr,
"use_dissolve_boundaries");
6191 for (
Object *obedit : objects) {
6195 if ((
bm->totvertsel == 0) && (
bm->totedgesel == 0) && (
bm->totfacesel == 0)) {
6237 "dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b delimit=%i",
6241 use_dissolve_boundaries,
6247 params.calc_looptris =
true;
6248 params.calc_normals =
false;
6249 params.is_destructive =
true;
6261 ot->name =
"Limited Dissolve";
6262 ot->idname =
"MESH_OT_dissolve_limited";
6264 "Dissolve selected edges and vertices, limited by the angle of surrounding geometry";
6285 "use_dissolve_boundaries",
6288 "Dissolve all vertices in between face boundaries");
6294 "Delimit dissolve operation");
6307 int totelem_old[3] = {0, 0, 0};
6308 int totelem_new[3] = {0, 0, 0};
6313 for (
Object *obedit : objects) {
6316 totelem_old[0] +=
bm->totvert;
6317 totelem_old[1] +=
bm->totedge;
6318 totelem_old[2] +=
bm->totface;
6323 for (
Object *obedit : objects) {
6335 params.calc_looptris =
true;
6336 params.calc_normals =
false;
6337 params.is_destructive =
true;
6340 totelem_new[0] +=
bm->totvert;
6341 totelem_new[1] +=
bm->totedge;
6342 totelem_new[2] +=
bm->totface;
6353 ot->name =
"Degenerate Dissolve";
6354 ot->idname =
"MESH_OT_dissolve_degenerate";
6355 ot->description =
"Dissolve zero area faces and zero length edges";
6370 "Maximum distance between elements to merge",
6390 for (
Object *obedit : objects) {
6417 "dissolve_edges edges=%he use_verts=%b use_face_split=%b angle_threshold=%f",
6432 params.calc_looptris =
true;
6433 params.calc_normals =
false;
6434 params.is_destructive =
true;
6444 ot->name =
"Delete Edge Loop";
6445 ot->description =
"Delete an edge loop by merging the faces on each side";
6446 ot->idname =
"MESH_OT_delete_edgeloop";
6459 "Split off face corners to maintain surrounding geometry");
6474 for (
Object *obedit : objects) {
6496 params.calc_looptris =
true;
6497 params.calc_normals =
true;
6498 params.is_destructive =
true;
6509 ot->idname =
"MESH_OT_split";
6510 ot->description =
"Split off selected geometry from connected unselected geometry";
6582 char *pblock[3] = {
nullptr,
nullptr,
nullptr}, *pb;
6583 BMElemSort *sblock[3] = {
nullptr,
nullptr,
nullptr}, *sb;
6584 uint *map[3] = {
nullptr,
nullptr,
nullptr}, *mp;
6585 int totelem[3] = {0, 0, 0};
6586 int affected[3] = {0, 0, 0};
6605 float fact = reverse ? -1.0 : 1.0;
6621 sb[affected[0]].org_idx =
i;
6622 sb[affected[0]++].srt = co[coidx] * fact;
6641 sb[affected[1]].org_idx =
i;
6642 sb[affected[1]++].srt = co[coidx] * fact;
6661 sb[affected[2]].org_idx =
i;
6662 sb[affected[2]++].srt = co[coidx] * fact;
6674 float fact = reverse ? -1.0 : 1.0;
6688 sb[affected[0]].org_idx =
i;
6707 sb[affected[1]].org_idx =
i;
6726 sb[affected[2]].org_idx =
i;
6747 sb[affected[2]].org_idx =
i;
6750 sb[affected[2]++].srt = srt *
float(totelem[2]) +
float(
i);
6760 uint *tbuf[3] = {
nullptr,
nullptr,
nullptr}, *tb;
6768 mp[affected[0]++] =
i;
6783 mp[affected[1]++] =
i;
6798 mp[affected[2]++] =
i;
6808 int tot = totelem[j];
6809 int aff = affected[j];
6815 if (
ELEM(aff, 0, tot)) {
6822 memcpy(tb + (tot - aff), mp, aff *
sizeof(
int));
6825 memcpy(mp + aff, tb, (tot - aff) *
sizeof(
int));
6827 mp = map[j] = tbuf[j];
6832 for (
i = tot, tb = tbuf[j] + tot - 1;
i--; tb--) {
6850 sb[affected[0]].org_idx =
i;
6869 sb[affected[1]].org_idx =
i;
6888 sb[affected[2]].org_idx =
i;
6908 sb[affected[0]].org_idx =
i;
6909 sb[affected[0]++].srt =
float(-
i);
6924 sb[affected[1]].org_idx =
i;
6925 sb[affected[1]++].srt =
float(-
i);
6940 sb[affected[2]].org_idx =
i;
6941 sb[affected[2]++].srt =
float(-
i);
6953 if (affected[0] == 0 && affected[1] == 0 && affected[2] == 0) {
6972 if (pb && sb && !map[j]) {
6975 int tot = totelem[j];
6976 int aff = affected[j];
6981 p_blk = pb + tot - 1;
6982 s_blk = sb + aff - 1;
6983 for (
i = tot;
i--; p_blk--) {
7004 params.calc_looptris = (totelem[2] != 0);
7005 params.calc_normals =
false;
7006 params.is_destructive =
true;
7035 if (rv3d ==
nullptr) {
7062 for (
uint ob_index = 0; ob_index < objects.
size(); ob_index++) {
7063 Object *ob = objects[ob_index];
7067 if (!((elem_types &
BM_VERT &&
bm->totvertsel > 0) ||
7068 (elem_types &
BM_EDGE &&
bm->totedgesel > 0) ||
7069 (elem_types &
BM_FACE &&
bm->totfacesel > 0)))
7074 int seed_iter =
seed;
7082 C, scene, ob, rv3d, elem_types,
BM_ELEM_SELECT, action, use_reverse, seed_iter);
7095 if (
STREQ(prop_id,
"seed")) {
7103 if (
STREQ(prop_id,
"reverse")) {
7120 "Sort selected elements from farthest to nearest one in current view"},
7125 "Sort selected elements from left to right one in current view"},
7130 "Sort selected elements from nearest to farthest from 3D cursor"},
7135 "Sort selected faces from smallest to greatest material index"},
7140 "Move all selected elements in first places, preserving their relative order.\n"
7141 "Warning: This will affect unselected elements' indices as well"},
7142 {
SRT_RANDOMIZE,
"RANDOMIZE", 0,
"Randomize",
"Randomize order of selected elements"},
7143 {
SRT_REVERSE,
"REVERSE", 0,
"Reverse",
"Reverse current order of selected elements"},
7144 {0,
nullptr, 0,
nullptr,
nullptr},
7148 {
BM_VERT,
"VERT", 0,
"Vertices",
""},
7149 {
BM_EDGE,
"EDGE", 0,
"Edges",
""},
7150 {
BM_FACE,
"FACE", 0,
"Faces",
""},
7151 {0,
nullptr, 0,
nullptr,
nullptr},
7155 ot->name =
"Sort Mesh Elements";
7157 "The order of selected vertices/edges/faces is modified, based on a given method";
7158 ot->idname =
"MESH_OT_sort_elements";
7175 "Type of reordering operation to apply");
7181 "Which elements to affect (vertices, edges and/or faces)");
7182 RNA_def_boolean(
ot->srna,
"reverse",
false,
"Reverse",
"Reverse the sorting effect");
7183 RNA_def_int(
ot->srna,
"seed", 0, 0, INT_MAX,
"Seed",
"Seed for random-based operations", 0, 255);
7204 int totface_del = 0;
7215 bool is_all_sel =
true;
7230 if (is_all_sel ==
false) {
7243 const bool use_pairs,
7244 const bool use_cyclic,
7245 const bool use_merge,
7246 const float merge_factor,
7247 const int twist_offset)
7251 int totface_del = 0;
7252 BMFace **totface_del_arr =
nullptr;
7254 bool changed =
false;
7271 totface_del_arr =
static_cast<BMFace **
>(
7272 MEM_mallocN(
sizeof(*totface_del_arr) * totface_del, __func__));
7277 totface_del_arr[
i++] = f;
7289 "bridge_loops edges=%he use_pairs=%b use_cyclic=%b use_merge=%b merge_factor=%f "
7298 if (use_faces && totface_del) {
7301 for (
i = 0;
i < totface_del;
i++) {
7306 "delete geom=%hf context=%i",
7316 if (use_merge ==
false) {
7324 if (use_merge ==
false) {
7328 if (op_props.
cuts) {
7336 "subdivide_edgering edges=%S interp_mode=%i cuts=%i smooth=%f "
7337 "profile_shape=%i profile_shape_factor=%f",
7355 if (totface_del_arr) {
7365 params.calc_looptris =
true;
7366 params.calc_normals =
false;
7367 params.is_destructive =
true;
7388 for (
Object *obedit : objects) {
7397 static_cast<Mesh *
>(obedit->data),
7413 {0,
nullptr, 0,
nullptr,
nullptr},
7417 ot->name =
"Bridge Edge Loops";
7418 ot->description =
"Create a bridge of faces between two or more selected edge loops";
7419 ot->idname =
"MESH_OT_bridge_edge_loops";
7433 "Method of bridging multiple loops");
7435 RNA_def_boolean(
ot->srna,
"use_merge",
false,
"Merge",
"Merge rather than creating faces");
7436 RNA_def_float(
ot->srna,
"merge_factor", 0.5f, 0.0f, 1.0f,
"Merge Factor",
"", 0.0f, 1.0f);
7443 "Twist offset for closed loops",
7471 for (
Object *obedit : objects) {
7483 "wireframe faces=%hf use_replace=%b use_boundary=%b use_even_offset=%b "
7484 "use_relative_offset=%b "
7485 "use_crease=%b crease_weight=%f thickness=%f offset=%f",
7490 use_relative_offset,
7507 params.calc_looptris =
true;
7508 params.calc_normals =
false;
7509 params.is_destructive =
true;
7521 ot->name =
"Wireframe";
7522 ot->idname =
"MESH_OT_wireframe";
7523 ot->description =
"Create a solid wireframe from faces";
7533 RNA_def_boolean(
ot->srna,
"use_boundary",
true,
"Boundary",
"Inset face boundaries");
7538 "Scale the offset to give more even thickness");
7540 "use_relative_offset",
7543 "Scale the offset by surrounding geometry");
7544 RNA_def_boolean(
ot->srna,
"use_replace",
true,
"Replace",
"Remove original faces");
7546 ot->srna,
"thickness", 0.01f, 0.0f, 1e4f,
"Thickness",
"", 0.0f, 10.0f);
7554 "Crease hub edges for an improved subdivision surface");
7556 ot->srna,
"crease_weight", 0.01f, 0.0f, 1e3f,
"Crease Weight",
"", 0.0f, 1.0f);
7569 bool changed_multi =
false;
7574 for (
Base *base : bases) {
7575 Object *obedit = base->object;
7586 "offset_edgeloops edges=%he use_cap_endpoint=%b",
7599 params.calc_looptris =
true;
7600 params.calc_normals =
false;
7601 params.is_destructive =
true;
7603 changed_multi =
true;
7607 if (changed_multi) {
7624 ot->name =
"Offset Edge Loop";
7625 ot->idname =
"MESH_OT_offset_edge_loops";
7626 ot->description =
"Create offset edge loop from the current selection";
7639 ot->srna,
"use_cap_endpoint",
false,
"Cap Endpoint",
"Extend loop around end-points");
7663 for (
Object *obedit : objects) {
7675 "convex_hull input=%hvef "
7676 "use_existing_faces=%b",
7678 use_existing_faces);
7691 if (delete_unused) {
7693 em, op,
"delete geom=%S context=%i", &bmop,
"geom_unused.out",
DEL_ONLYTAGGED))
7703 em, op,
"delete geom=%S context=%i", &bmop,
"geom_holes.out",
DEL_ONLYTAGGED))
7711 if (join_triangles) {
7716 "join_triangles faces=%S "
7717 "angle_face_threshold=%f angle_shape_threshold=%f",
7720 angle_face_threshold,
7721 angle_shape_threshold))
7733 params.calc_looptris =
true;
7734 params.calc_normals =
false;
7735 params.is_destructive =
true;
7748 ot->name =
"Convex Hull";
7749 ot->description =
"Enclose selected vertices in a convex polyhedron";
7750 ot->idname =
"MESH_OT_convex_hull";
7753 ot->exec = edbm_convex_hull_exec;
7764 "Delete selected elements that are not used by the hull");
7767 "use_existing_faces",
7769 "Use Existing Faces",
7770 "Skip hull triangles that are covered by a pre-existing face");
7776 "Delete selected faces that are used by the hull");
7779 ot->srna,
"join_triangles",
true,
"Join Triangles",
"Merge adjacent triangles into quads");
7799 for (
Object *obedit : objects) {
7810 "symmetrize input=%hvef direction=%i dist=%f",
7825 bool calc_normals =
false;
7832 params.calc_looptris =
true;
7833 params.calc_normals = calc_normals;
7834 params.is_destructive =
true;
7847 ot->name =
"Symmetrize";
7848 ot->description =
"Enforce symmetry (both form and topological) across an axis";
7849 ot->idname =
"MESH_OT_symmetrize";
7863 "Which sides to copy from and to");
7870 "Limit for snap middle vertices to the axis center",
7883 const float eps = 0.00001f;
7884 const float eps_sq =
eps *
eps;
7885 const bool use_topology =
false;
7893 int totvertfound = 0, totvertmirr = 0, totvertfail = 0, totobjects = 0;
7896 int axis = axis_dir % 3;
7897 bool axis_sign = axis != axis_dir;
7904 for (
Object *obedit : objects) {
7936 int i_mirr = index[
i];
7942 float co[3], co_mirr[3];
7944 if ((
v->co[axis] > v_mirr->
co[axis]) == axis_sign) {
7945 std::swap(
v, v_mirr);
7949 co_mirr[axis] *= -1.0f;
7985 params.calc_looptris =
false;
7986 params.calc_normals =
false;
7987 params.is_destructive =
false;
7997 "%d already symmetrical, %d pairs mirrored, %d failed",
7998 totvertfound - totvertmirr,
8002 else if (totobjects) {
8005 "%d already symmetrical, %d pairs mirrored",
8006 totvertfound - totvertmirr,
8016 ot->name =
"Snap to Symmetry";
8017 ot->description =
"Snap vertex pairs to their mirrored locations";
8018 ot->idname =
"MESH_OT_symmetry_snap";
8032 "Which sides to copy from and to");
8039 "Distance within which matching vertices are searched",
8048 "Mix factor of the locations of the vertices",
8052 ot->srna,
"use_center",
true,
"Center",
"Snap middle vertices to the axis center");
8057#if defined(WITH_FREESTYLE)
8073 for (
Object *obedit : objects) {
8076 if (em ==
nullptr) {
8082 if (
bm->totedgesel == 0) {
8119 ot->name =
"Mark Freestyle Edge";
8120 ot->description =
"(Un)mark selected edges as Freestyle feature edges";
8121 ot->idname =
"MESH_OT_mark_freestyle_edge";
8124 ot->exec = edbm_mark_freestyle_edge_exec;
8150 for (
Object *obedit : objects) {
8153 if (em ==
nullptr) {
8194 ot->name =
"Mark Freestyle Face";
8195 ot->description =
"(Un)mark selected faces for exclusion from Freestyle feature edge detection";
8196 ot->idname =
"MESH_OT_mark_freestyle_face";
8199 ot->exec = edbm_mark_freestyle_face_exec;
8250 "Toggle inversion of affected normals"},
8255 "Interpolate between new and original normals"},
8262 "Follow mouse cursor position"},
8267 "Use current rotation/scaling pivot point coordinates"},
8272 "Use current edited object's location"},
8276 "Set and Use 3D Cursor",
8277 "Set new 3D cursor position and use it"},
8281 "Select and Use Mesh Item",
8282 "Select new active mesh element and use its location"},
8283 {0,
nullptr, 0,
nullptr,
nullptr},
8285 static const char *keymap_name =
"Custom Normals Modal Map";
8301#define CLNORS_VALID_VEC_LEN (1e-4f)
8319 "Use static coordinates (defined by various means)"},
8321 {0,
nullptr, 0,
nullptr,
nullptr},
8336 return (lnors_ed_arr->
totloop != 0);
8424 if (do_align && !do_reset) {
8431 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
8435 else if (do_spherize) {
8439 float spherized_normal[3];
8450 else if (do_align) {
8457 if (do_invert && !do_reset) {
8486 int new_mode = mode;
8487 bool force_mousemove =
false;
8488 bool do_reset =
false;
8493 switch (event->
val) {
8539 force_mousemove =
true;
8626 if (new_mode != mode) {
8653 params.calc_looptris =
true;
8654 params.calc_normals =
false;
8655 params.is_destructive =
false;
8718 params.calc_looptris =
true;
8719 params.calc_normals =
false;
8720 params.is_destructive =
false;
8732 if (
STREQ(prop_id,
"spherize_strength")) {
8762 ot->name =
"Point Normals to Target";
8763 ot->description =
"Point selected custom normals to specified Target";
8764 ot->idname =
"MESH_OT_point_normals";
8782 "How to define coordinates to point custom normals to");
8785 RNA_def_boolean(
ot->srna,
"invert",
false,
"Invert",
"Invert affected normals");
8787 RNA_def_boolean(
ot->srna,
"align",
false,
"Align",
"Make all affected normals parallel");
8796 "Target location to which normals will point",
8801 ot->srna,
"spherize",
false,
"Spherize",
"Interpolate between original and new normals");
8804 "spherize_strength",
8808 "Spherize Strength",
8809 "Ratio of spherized normal to original normal",
8830 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
8841 float avg_normal[3] = {0.0f, 0.0f, 0.0f};
8844 for (; loops; loops = loops->
next) {
8894 bm->lnor_spacearr->lspacearr[loop_index], f->
no, clnors);
8900 const BMEdge *e_org = l_curr->
e;
8901 BMLoop *lfan_pivot, *lfan_pivot_next;
8903 lfan_pivot = l_curr;
8904 e_next = lfan_pivot->
e;
8905 float avg_normal[3] = {0.0f};
8909 if (lfan_pivot_next) {
8913 e_next = (lfan_pivot->
e == e_next) ? lfan_pivot->
prev->
e : lfan_pivot->
e;
8922 lfan_pivot = lfan_pivot_next;
8932 bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
8936 }
while ((l_curr = l_curr->
next) != l_first);
8947 for (
Object *obedit : objects) {
8985 params.calc_looptris =
true;
8986 params.calc_normals =
false;
8987 params.is_destructive =
false;
9002 ot->name =
"Merge Normals";
9003 ot->description =
"Merge custom normals of selected vertices";
9004 ot->idname =
"MESH_OT_merge_normals";
9022 ot->name =
"Split Normals";
9023 ot->description =
"Split custom normals of selected vertices";
9024 ot->idname =
"MESH_OT_split_normals";
9051 "Take average of vertex normals"},
9056 "Set all vertex normals by face area"},
9061 "Set all vertex normals by corner angle"},
9062 {0,
nullptr, 0,
nullptr,
nullptr},
9078 for (
uint ob_index = 0; ob_index < objects.
size(); ob_index++) {
9082 Object *obedit = objects[ob_index];
9095 float weight = absweight / 50.0f;
9096 if (absweight == 100.0f) {
9097 weight =
float(SHRT_MAX);
9099 else if (absweight == 1.0f) {
9100 weight = 1 /
float(SHRT_MAX);
9102 else if ((weight - 1) * 25 > 1) {
9103 weight = (weight - 1) * 25;
9121 bm->lnor_spacearr->lspacearr[loop_index], f->
no, clnors);
9127 const BMEdge *e_org = l_curr->
e;
9128 BMLoop *lfan_pivot, *lfan_pivot_next;
9130 lfan_pivot = l_curr;
9131 e_next = lfan_pivot->
e;
9135 if (lfan_pivot_next) {
9139 e_next = (lfan_pivot->
e == e_next) ? lfan_pivot->
prev->
e : lfan_pivot->
e;
9155 lfan_pivot = lfan_pivot_next;
9158 float wnor[3], avg_normal[3] = {0.0f},
count = 0;
9170 const float n_weight =
pow(weight,
count);
9176 bm->lnor_spacearr->lspacearr[l_index], clnors, wnor);
9181 mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
9193 bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
9197 }
while ((l_curr = l_curr->
next) != l_first);
9201 params.calc_looptris =
true;
9202 params.calc_normals =
false;
9203 params.is_destructive =
false;
9221 if (
STREQ(prop_id,
"weight")) {
9222 return !is_clor_average_loop;
9224 if (
STREQ(prop_id,
"threshold")) {
9225 return !is_clor_average_loop;
9254 ot->name =
"Average Normals";
9255 ot->description =
"Average custom normals of selected vertices";
9256 ot->idname =
"MESH_OT_average_normals";
9271 "Averaging method");
9273 RNA_def_int(
ot->srna,
"weight", 50, 1, 100,
"Weight",
"Weight applied per face", 1, 100);
9281 "Threshold value for different weights to be considered equal",
9306 "Paste normal from the internal clipboard"},
9312 "Multiply normal vector with selection"},
9317 "Reset the internal clipboard and/or normal of selected element"},
9318 {0,
nullptr, 0,
nullptr,
nullptr},
9330 bool done_copy =
false;
9332 for (
Object *obedit : objects) {
9336 if (
bm->totloop == 0) {
9346 if (
bm->totfacesel == 0 &&
bm->totvertsel == 0) {
9352 (
bm->totfacesel != 1 && lnors_ed_arr->
totloop != 1 &&
bm->totvertsel != 1))
9356 "Can only copy one custom normal, vertex normal or face normal");
9360 if (lnors_ed_arr->
totloop == 1) {
9363 else if (
bm->totfacesel == 1) {
9375 bool are_same_lnors =
true;
9376 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
9378 are_same_lnors =
false;
9381 if (are_same_lnors) {
9395 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
9397 float abs_normal[3];
9419 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
9433 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
9448 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
9463 params.calc_looptris =
true;
9464 params.calc_normals =
false;
9465 params.is_destructive =
false;
9478 if (
STREQ(prop_id,
"absolute")) {
9506 ot->name =
"Normals Vector Tools";
9507 ot->description =
"Custom normals tools using Normal Vector of UI";
9508 ot->idname =
"MESH_OT_normals_tools";
9523 "Mode of tools taking input from interface");
9529 "Absolute Coordinates",
9530 "Copy Absolute coordinates of Normal vector");
9546 for (
Object *obedit : objects) {
9549 if (
bm->totfacesel == 0) {
9557 BMIter fiter, viter, eiter, liter;
9563 float (*vert_normals)[3] =
static_cast<float (*)[3]
>(
9564 MEM_mallocN(
sizeof(*vert_normals) *
bm->totvert, __func__));
9589 bm->lnor_spacearr->lspacearr[l_index], vert_normals[v_index], clnors);
9595 LinkNode *loops =
bm->lnor_spacearr->lspacearr[l_index]->loops;
9596 for (; loops; loops = loops->
next) {
9613 bm->lnor_spacearr->lspacearr[loop_index], vert_normals[v_index], clnors);
9621 params.calc_looptris =
true;
9622 params.calc_normals =
false;
9623 params.is_destructive =
false;
9633 ot->name =
"Set Normals from Faces";
9634 ot->description =
"Set the custom normals from the selected faces ones";
9635 ot->idname =
"MESH_OT_set_normals_from_faces";
9645 ot->srna,
"keep_sharp",
false,
"Keep Sharp Edges",
"Do not set sharp edges to face");
9661 for (
Object *obedit : objects) {
9671 float (*smooth_normal)[3] =
static_cast<float (*)[3]
>(
9682 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
9684 float loop_normal[3];
9690 short *clnors =
static_cast<short *
>(
9693 bm->lnor_spacearr->lspacearr[l_index_other], clnors, loop_normal);
9702 for (
int i = 0;
i < lnors_ed_arr->
totloop;
i++, lnor_ed++) {
9703 float current_normal[3];
9715 mul_v3_fl(current_normal, 1.0f - factor);
9732 params.calc_looptris =
true;
9733 params.calc_normals =
false;
9734 params.is_destructive =
false;
9744 ot->name =
"Smooth Normals Vectors";
9745 ot->description =
"Smooth custom normals based on adjacent vertex normals";
9746 ot->idname =
"MESH_OT_smooth_normals";
9761 "Specifies weight of smooth vs original normal",
9779 for (
Object *obedit : objects) {
9791 if (cd_prop_int_index == -1) {
9805 *strength = face_strength;
9812 if (*strength == face_strength) {
9823 params.calc_looptris =
false;
9824 params.calc_normals =
false;
9825 params.is_destructive =
false;
9836 {0,
nullptr, 0,
nullptr,
nullptr},
9842 ot->name =
"Face Normals Strength";
9843 ot->description =
"Set/Get strength of face (used in Weighted Normal modifier)";
9844 ot->idname =
"MESH_OT_mod_weighted_strength";
9861 "Strength to use for assigning or selecting face influence for weighted normal modifier");
9867 ot->name =
"Flip Quad Tessellation";
9868 ot->description =
"Flips the tessellation of selected quads";
9869 ot->idname =
"MESH_OT_flip_quad_tessellation";
Generic geometry attributes built on CustomData.
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, blender::StringRef name, eCustomDataMask type, AttrDomainMask domain_mask)
#define CTX_DATA_BEGIN(C, Type, instance, member)
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)
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
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.
void BKE_objects_materials_sync_length_all(Main *bmain, ID *id)
short * BKE_object_material_len_p(Object *ob)
void BKE_id_material_clear(Main *bmain, ID *id)
short * BKE_id_material_len_p(ID *id)
Material *** BKE_id_material_array_p(ID *id)
void BKE_id_material_resize(Main *bmain, ID *id, short totcol, bool do_id_user)
void BKE_object_material_array_assign(Main *bmain, Object *ob, Material ***matar, int totcol, bool to_object_only)
Material *** BKE_object_material_array_p(Object *ob)
void BKE_lnor_space_custom_data_to_normal(const MLoopNorSpace *lnor_space, const short clnor_data[2], float r_custom_lnor[3])
void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space, const float custom_lnor[3], short r_clnor_data[2])
@ MLNOR_SPACEARR_BMLOOP_PTR
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)
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_listbase_rotate_first(ListBase *lb, void *vlink) ATTR_NONNULL(1
int BLI_listbase_count_at_most(const 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)
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)
MINLINE int count_bits_i(unsigned int n)
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
#define BLT_I18NCONTEXT_ID_MESH
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 void EDBM_redo_state_restore_and_free(BMBackup *backup, BMEditMesh *em, bool recalc_looptris) ATTR_NONNULL(1
void EDBM_select_flush_from_verts(BMEditMesh *em, bool select)
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params)
bool EDBM_uvselect_clear(BMEditMesh *em)
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)
bool EDBM_automerge_connected(Object *obedit, bool update, char hflag, float dist)
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)
bool EDBM_automerge(Object *obedit, bool update, char hflag, float dist)
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)
bool EDBM_select_pick(bContext *C, const int mval[2], const SelectPick_Params ¶ms)
void ED_outliner_select_sync_from_object_tag(bContext *C)
bool ED_operator_scene_editable(bContext *C)
void ED_workspace_status_text(bContext *C, const char *str)
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 ED_view3d_cursor3d_update(bContext *C, const int mval[2], bool use_depth, enum eV3DCursorOrient orientation)
void view3d_operator_needs_gpu(const bContext *C)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Read Guarded memory(de)allocation.
@ 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)
#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_SET_BOOL(ele, offset, f)
#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_named(BMesh *bm, CustomData *data, int type, const StringRef name)
void BM_data_layer_ensure_named(BMesh *bm, CustomData *data, int type, const StringRef 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)
BMesh const char void * data
BMVert * BM_mesh_active_vert_get(BMesh *bm)
void BM_select_history_clear(BMesh *bm)
char BM_select_history_htype_all(const 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)
BMLoopNorEditDataArray * BM_loop_normal_editdata_array_init_with_htype(BMesh *bm, const bool do_all_loops_of_vert, const char htype_override)
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)
@ DEL_FACES_KEEP_BOUNDARY
@ 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_iter_map_value_ptr(BMOIter *iter)
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.
void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, char hflag)
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_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int i)
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,...)
#define BMO_FLAG_DEFAULTS
BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val)
@ 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
static bool UNUSED_FUNCTION EDBM_select_mirrored_extend_all(Object *obedit, BMEditMesh *em)
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)
BLI_INLINE float fb(float length, float L)
void * MEM_mallocN(size_t len, const char *str)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
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_discrete(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_int_default(PropertyRNA *prop, int value)
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
MeshRuntimeHandle * runtime
char * active_color_attribute
ObjectRuntimeHandle * runtime
struct ToolSettings * toolsettings
void use_property_decorate_set(bool is_sep)
uiLayout & column(bool align)
void prop_search(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop, PropertyRNA *item_searchpropname, std::optional< blender::StringRefNull > name, int icon, bool results_are_suggestions)
uiLayout & row(bool align)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
struct ReportList * reports
struct wmOperatorType * type
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
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)
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)
void WM_operatortype_props_advanced_begin(wmOperatorType *ot)
void WM_operator_type_modal_from_exec_for_object_edit_coords(wmOperatorType *ot)
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)