Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/mesh/editmesh_tools.c')
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c509
1 files changed, 420 insertions, 89 deletions
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 879e20fcf8b..0c5c756a0fc 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -41,7 +41,9 @@
#include "RNA_define.h"
#include "RNA_access.h"
+#include "BLI_array.h"
#include "BLI_blenlib.h"
+#include "BLI_noise.h"
#include "BLI_math.h"
#include "BLI_rand.h"
@@ -49,6 +51,7 @@
#include "BKE_context.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_depsgraph.h"
+#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_texture.h"
@@ -72,6 +75,8 @@
#include "mesh_intern.h"
+#define MVAL_PIXEL_MARGIN 5.0f
+
/* allow accumulated normals to form a new direction but don't
* accept direct opposite directions else they will cancel each other out */
static void add_normal_aligned(float nor[3], const float add[3])
@@ -153,6 +158,51 @@ void MESH_OT_subdivide(wmOperatorType *ot)
}
+static int edbm_unsubdivide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BMEdit_FromObject(obedit);
+ BMOperator bmop;
+
+ int iterations = RNA_int_get(op->ptr, "iterations");
+
+ EDBM_op_init(em, &bmop, op,
+ "unsubdivide verts=%hv iterations=%i", BM_ELEM_SELECT, iterations);
+
+ BMO_op_exec(em->bm, &bmop);
+
+ if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ return 0;
+ }
+
+ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); /* need to flush vert->face first */
+ }
+ EDBM_selectmode_flush(em);
+
+ EDBM_update_generic(C, em, TRUE);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_unsubdivide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Un-Subdivide";
+ ot->description = "UnSubdivide selected edges & faces";
+ ot->idname = "MESH_OT_unsubdivide";
+
+ /* api callbacks */
+ ot->exec = edbm_unsubdivide_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_int(ot->srna, "iterations", 2, 1, INT_MAX, "Iterations", "Number of times to unsubdivide", 1, 100);
+}
+
void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
{
Object *obedit = em->ob;
@@ -165,7 +215,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
float mval[2], co_proj[3], no_dummy[3];
int dist_dummy;
- if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) {
+ if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
if (snapObjectsContext(C, mval, &dist_dummy, co_proj, no_dummy, SNAP_NOT_OBEDIT)) {
mul_v3_m4v3(eve->co, obedit->imat, co_proj);
}
@@ -205,7 +255,7 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c
return 0;
}
- return 's'; // s is shrink/fatten
+ return 's'; /* s is shrink/fatten */
}
/* extrudes individual edges */
@@ -225,7 +275,7 @@ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char
return 0;
}
- return 'n'; // n is normal grab
+ return 'n'; /* n is normal grab */
}
/* extrudes individual vertices */
@@ -245,7 +295,7 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char
return 0;
}
- return 'g'; // g is grab
+ return 'g'; /* g is grab */
}
static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, float nor[3])
@@ -429,8 +479,8 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX);
- RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX);
+ RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, FLT_MAX, "Offset", "", 0.0f, 100.0f);
+ RNA_def_int(ot->srna, "steps", 10, 0, INT_MAX, "Steps", "", 0, 180);
}
/* generic extern called extruder */
@@ -765,10 +815,10 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
done = FALSE;
BM_ITER_MESH (eed, &iter, vc.em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- float co1[3], co2[3];
+ float co1[2], co2[2];
- if ((ED_view3d_project_float_object(vc.ar, eed->v1->co, co1, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) &&
- (ED_view3d_project_float_object(vc.ar, eed->v2->co, co2, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS))
+ if ((ED_view3d_project_float_object(vc.ar, eed->v1->co, co1, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
+ (ED_view3d_project_float_object(vc.ar, eed->v2->co, co2, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
{
/* 2D rotate by 90d while adding.
* (x, y) = (y, -x)
@@ -1215,10 +1265,13 @@ static int edbm_vert_connect(bContext *C, wmOperator *op)
if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
return OPERATOR_CANCELLED;
}
-
- EDBM_update_generic(C, em, TRUE);
+ else {
+ EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */
- return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ EDBM_update_generic(C, em, TRUE);
+
+ return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ }
}
void MESH_OT_vert_connect(wmOperatorType *ot)
@@ -1607,12 +1660,94 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Number of times to smooth the mesh", "", 1, 100);
RNA_def_boolean(ot->srna, "xaxis", 1, "X-Axis", "Smooth along the X axis");
RNA_def_boolean(ot->srna, "yaxis", 1, "Y-Axis", "Smooth along the Y axis");
RNA_def_boolean(ot->srna, "zaxis", 1, "Z-Axis", "Smooth along the Z axis");
}
+static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BMEdit_FromObject(obedit);
+ int usex = TRUE, usey = TRUE, usez = TRUE, volume_preservation = TRUE;
+ int i, repeat;
+ float lambda;
+ float lambda_border;
+ BMIter fiter;
+ BMFace *f;
+
+ /* Check if select faces are triangles */
+ BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ if (f->len > 4) {
+ BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+
+ /* mirror before smooth */
+ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
+ EDBM_verts_mirror_cache_begin(em, TRUE);
+ }
+
+ repeat = RNA_int_get(op->ptr, "repeat");
+ lambda = RNA_float_get(op->ptr, "lambda");
+ lambda_border = RNA_float_get(op->ptr, "lambda_border");
+ usex = RNA_boolean_get(op->ptr, "use_x");
+ usey = RNA_boolean_get(op->ptr, "use_y");
+ usez = RNA_boolean_get(op->ptr, "use_z");
+ volume_preservation = RNA_boolean_get(op->ptr, "volume_preservation");
+ if (!repeat)
+ repeat = 1;
+
+ for (i = 0; i < repeat; i++) {
+ if (!EDBM_op_callf(em, op,
+ "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b volume_preservation=%b",
+ BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, volume_preservation))
+ {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* apply mirror */
+ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
+ EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0);
+ EDBM_verts_mirror_cache_end(em);
+ }
+
+ EDBM_update_generic(C, em, TRUE);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Laplacian Smooth Vertex";
+ ot->description = "Laplacian smooth of selected vertices";
+ ot->idname = "MESH_OT_vertices_smooth_laplacian";
+
+ /* api callbacks */
+ ot->exec = edbm_do_smooth_laplacian_vertex_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "repeat", 1, 1, 200,
+ "Number of iterations to smooth the mesh", "", 1, 200);
+ RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f,
+ "Lambda factor", "", 0.0000001f, 1000.0f);
+ RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f,
+ "Lambda factor in border", "", 0.0000001f, 1000.0f);
+ RNA_def_boolean(ot->srna, "use_x", 1, "Smooth X Axis", "Smooth object along X axis");
+ RNA_def_boolean(ot->srna, "use_y", 1, "Smooth Y Axis", "Smooth object along Y axis");
+ RNA_def_boolean(ot->srna, "use_z", 1, "Smooth Z Axis", "Smooth object along Z axis");
+ RNA_def_boolean(ot->srna, "volume_preservation", 1, "Preserve Volume", "Apply volume preservation after smooth");
+}
+
/********************** Smooth/Solid Operators *************************/
static void mesh_set_smooth_faces(BMEditMesh *em, short smooth)
@@ -2080,7 +2215,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
}
count = totvert_orig - em->bm->totvert;
- BKE_reportf(op->reports, RPT_INFO, "Removed %d vert%s", count, (count == 1) ? "ex" : "ices");
+ BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count);
EDBM_update_generic(C, em, TRUE);
@@ -2165,7 +2300,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op)
}
if (svert == NULL || evert == NULL) {
- BKE_report(op->reports, RPT_WARNING, "Path Selection requires that two vertices be selected");
+ BKE_report(op->reports, RPT_WARNING, "Path selection requires two vertices to be selected");
return OPERATOR_CANCELLED;
}
@@ -2659,21 +2794,21 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
m1 = MAXSLOPE;
b1 = x12;
}
- x2max = maxf(x21, x22) + 0.001f; /* prevent missed edges */
- x2min = minf(x21, x22) - 0.001f; /* due to round off error */
- y2max = maxf(y21, y22) + 0.001f;
- y2min = minf(y21, y22) - 0.001f;
+ x2max = max_ff(x21, x22) + 0.001f; /* prevent missed edges */
+ x2min = min_ff(x21, x22) - 0.001f; /* due to round off error */
+ y2max = max_ff(y21, y22) + 0.001f;
+ y2min = min_ff(y21, y22) - 0.001f;
/* Found an intersect, calc intersect point */
if (m1 == m2) { /* co-incident lines */
/* cut at 50% of overlap area */
- x1max = maxf(x11, x12);
- x1min = minf(x11, x12);
- xi = (minf(x2max, x1max) + maxf(x2min, x1min)) / 2.0f;
+ x1max = max_ff(x11, x12);
+ x1min = min_ff(x11, x12);
+ xi = (min_ff(x2max, x1max) + max_ff(x2min, x1min)) / 2.0f;
- y1max = maxf(y11, y12);
- y1min = minf(y11, y12);
- yi = (minf(y2max, y1max) + maxf(y2min, y1min)) / 2.0f;
+ y1max = max_ff(y11, y12);
+ y1min = min_ff(y11, y12);
+ yi = (min_ff(y2max, y1max) + max_ff(y2min, y1min)) / 2.0f;
}
else if (m2 == MAXSLOPE) {
xi = x22;
@@ -2713,7 +2848,7 @@ static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2],
break;
}
- }
+ }
lastdist = dist;
}
return perc;
@@ -2772,7 +2907,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
screen_vert_coords = sco = MEM_mallocN(bm->totvert * sizeof(float) * 2, __func__);
BM_ITER_MESH_INDEX (bv, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (ED_view3d_project_float_object(ar, bv->co, *sco, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_SUCCESS) {
+ if (ED_view3d_project_float_object(ar, bv->co, *sco, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
copy_v2_fl(*sco, FLT_MAX); /* set error value */
}
BM_elem_index_set(bv, i); /* set_ok */
@@ -3078,7 +3213,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
}
else {
if (type == 0) {
- BKE_report(op->reports, RPT_ERROR, "Selecton not supported in object mode");
+ BKE_report(op->reports, RPT_ERROR, "Selection not supported in object mode");
return OPERATOR_CANCELLED;
}
@@ -3359,7 +3494,8 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
BMesh *bm = em->bm;
- float angle_limit = RNA_float_get(op->ptr, "angle_limit");
+ const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
+ const int use_dissolve_boundaries = RNA_boolean_get(op->ptr, "use_dissolve_boundaries");
char dissolve_flag;
@@ -3395,8 +3531,8 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
}
if (!EDBM_op_callf(em, op,
- "dissolve_limit edges=%he verts=%hv angle_limit=%f",
- dissolve_flag, dissolve_flag, angle_limit))
+ "dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b",
+ dissolve_flag, dissolve_flag, angle_limit, use_dissolve_boundaries))
{
return OPERATOR_CANCELLED;
}
@@ -3423,8 +3559,10 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f),
- "Max Angle", "Angle Limit in Degrees", 0.0f, DEG2RADF(180.0f));
+ "Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f));
RNA_def_property_float_default(prop, DEG2RADF(15.0f));
+ RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries",
+ "Dissolve all vertices inbetween face boundaries");
}
static int edbm_split_exec(bContext *C, wmOperator *op)
@@ -3542,7 +3680,7 @@ void MESH_OT_spin(wmOperatorType *ot)
RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f);
RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f);
}
@@ -3666,34 +3804,40 @@ void MESH_OT_screw(wmOperatorType *ot)
RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX,
"Center", "Center in global view space", -FLT_MAX, FLT_MAX);
- RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f,
- "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX,
+ "Axis", "Axis in global view space", -1.0f, 1.0f);
}
-static int edbm_select_by_number_vertices_exec(bContext *C, wmOperator *op)
+static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
BMFace *efa;
BMIter iter;
- int numverts = RNA_int_get(op->ptr, "number");
- int type = RNA_enum_get(op->ptr, "type");
+ const int numverts = RNA_int_get(op->ptr, "number");
+ const int type = RNA_enum_get(op->ptr, "type");
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- int select = 0;
+ int select;
- if (type == 0 && efa->len < numverts) {
- select = 1;
- }
- else if (type == 1 && efa->len == numverts) {
- select = 1;
- }
- else if (type == 2 && efa->len > numverts) {
- select = 1;
- }
- else if (type == 3 && efa->len != numverts) {
- select = 1;
+ switch (type) {
+ case 0:
+ select = (efa->len < numverts);
+ break;
+ case 1:
+ select = (efa->len == numverts);
+ break;
+ case 2:
+ select = (efa->len > numverts);
+ break;
+ case 3:
+ select = (efa->len != numverts);
+ break;
+ default:
+ BLI_assert(0);
+ select = FALSE;
+ break;
}
if (select) {
@@ -3707,7 +3851,7 @@ static int edbm_select_by_number_vertices_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void MESH_OT_select_by_number_vertices(wmOperatorType *ot)
+void MESH_OT_select_face_by_sides(wmOperatorType *ot)
{
static const EnumPropertyItem type_items[] = {
{0, "LESS", 0, "Less Than", ""},
@@ -3718,12 +3862,12 @@ void MESH_OT_select_by_number_vertices(wmOperatorType *ot)
};
/* identifiers */
- ot->name = "Select by Number of Vertices";
- ot->description = "Select vertices or faces by vertex count";
- ot->idname = "MESH_OT_select_by_number_vertices";
+ ot->name = "Select Faces by Sides";
+ ot->description = "Select vertices or faces by the number of polygon sides";
+ ot->idname = "MESH_OT_select_face_by_sides";
/* api callbacks */
- ot->exec = edbm_select_by_number_vertices_exec;
+ ot->exec = edbm_select_face_by_sides_exec;
ot->poll = ED_operator_editmesh;
/* flags */
@@ -3851,8 +3995,8 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
char *pblock[3] = {NULL, NULL, NULL}, *pb;
BMElemSort *sblock[3] = {NULL, NULL, NULL}, *sb;
int *map[3] = {NULL, NULL, NULL}, *mp;
- int totelem[3] = {0, 0, 0}, tot;
- int affected[3] = {0, 0, 0}, aff;
+ int totelem[3] = {0, 0, 0};
+ int affected[3] = {0, 0, 0};
int i, j;
if (!(types && flag && action))
@@ -4227,8 +4371,8 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
if (pb && sb && !map[j]) {
char *p_blk;
BMElemSort *s_blk;
- tot = totelem[j];
- aff = affected[j];
+ int tot = totelem[j];
+ int aff = affected[j];
qsort(sb, aff, sizeof(BMElemSort), bmelemsort_comp);
@@ -4277,7 +4421,7 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op)
if (ELEM(action, SRT_VIEW_ZAXIS, SRT_VIEW_XAXIS)) {
if (rv3d == NULL) {
- BKE_report(op->reports, RPT_ERROR, "View not found, can't sort by view axis");
+ BKE_report(op->reports, RPT_ERROR, "View not found, cannot sort by view axis");
return OPERATOR_CANCELLED;
}
}
@@ -4458,13 +4602,18 @@ void MESH_OT_noise(wmOperatorType *ot)
RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f);
}
+#define NEW_BEVEL 1
+
typedef struct {
BMEditMesh *em;
BMBackup mesh_backup;
+#ifndef NEW_BEVEL
float *weights;
int li;
+#endif
int mcenter[2];
float initial_length;
+ float pixel_size; /* use when mouse input is interpreted as spatial distance */
int is_modal;
NumInput num_input;
float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */
@@ -4474,13 +4623,25 @@ typedef struct {
static void edbm_bevel_update_header(wmOperator *op, bContext *C)
{
+#ifdef NEW_BEVEL
+ static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), offset: %s, segments: %d";
+#else
static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), factor: %s, Use Dist (D): %s: Use Even (E): %s";
+ BevelData *opdata = op->customdata;
+#endif
char msg[HEADER_LENGTH];
ScrArea *sa = CTX_wm_area(C);
- BevelData *opdata = op->customdata;
if (sa) {
+#ifdef NEW_BEVEL
+ char offset_str[NUM_STR_REP_LEN];
+ BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset"));
+ BLI_snprintf(msg, HEADER_LENGTH, str,
+ offset_str,
+ RNA_int_get(op->ptr, "segments")
+ );
+#else
char factor_str[NUM_STR_REP_LEN];
if (hasNumInput(&opdata->num_input))
outputNumInput(&opdata->num_input, factor_str);
@@ -4491,11 +4652,13 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C)
RNA_boolean_get(op->ptr, "use_dist") ? "On" : "Off",
RNA_boolean_get(op->ptr, "use_even") ? "On" : "Off"
);
+#endif
ED_area_headerprint(sa, msg);
}
}
+#ifndef NEW_BEVEL
static void edbm_bevel_recalc_weights(wmOperator *op)
{
float df, s, ftot;
@@ -4523,15 +4686,20 @@ static void edbm_bevel_recalc_weights(wmOperator *op)
mul_vn_fl(opdata->weights, recursion, 1.0f / (float)ftot);
}
+#endif
static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
+#ifdef NEW_BEVEL
+ BevelData *opdata;
+#else
BMIter iter;
BMEdge *eed;
BevelData *opdata;
int li;
+#endif
if (em == NULL) {
return 0;
@@ -4539,6 +4707,7 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
+#ifndef NEW_BEVEL
BM_data_layer_add(em->bm, &em->bm->edata, CD_PROP_FLT);
li = CustomData_number_of_layers(&em->bm->edata, CD_PROP_FLT) - 1;
@@ -4548,10 +4717,12 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
*dv = d;
}
-
- opdata->em = em;
+
opdata->li = li;
opdata->weights = NULL;
+#endif
+
+ opdata->em = em;
opdata->is_modal = is_modal;
opdata->shift_factor = -1.0f;
@@ -4561,7 +4732,9 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
/* avoid the cost of allocating a bm copy */
if (is_modal)
opdata->mesh_backup = EDBM_redo_state_store(em);
+#ifndef NEW_BEVEL
edbm_bevel_recalc_weights(op);
+#endif
return 1;
}
@@ -4571,6 +4744,26 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op)
BevelData *opdata = op->customdata;
BMEditMesh *em = opdata->em;
BMOperator bmop;
+#ifdef NEW_BEVEL
+ float offset = RNA_float_get(op->ptr, "offset");
+ int segments = RNA_int_get(op->ptr, "segments");
+
+ /* revert to original mesh */
+ if (opdata->is_modal) {
+ EDBM_redo_state_restore(opdata->mesh_backup, em, FALSE);
+ }
+
+ if (!EDBM_op_init(em, &bmop, op,
+ "bevel geom=%hev offset=%f segments=%i",
+ BM_ELEM_SELECT, offset, segments))
+ {
+ return 0;
+ }
+
+ BMO_op_exec(em->bm, &bmop);
+ if (!EDBM_op_finish(em, &bmop, op, TRUE))
+ return 0;
+#else
int i;
float factor = RNA_float_get(op->ptr, "percent") /*, dfac */ /* UNUSED */;
@@ -4598,6 +4791,7 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op)
if (!EDBM_op_finish(em, &bmop, op, TRUE))
return 0;
}
+#endif
EDBM_mesh_normals_update(opdata->em);
@@ -4615,10 +4809,12 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
if (sa) {
ED_area_headerprint(sa, NULL);
}
+#ifndef NEW_BEVEL
BM_data_layer_free_n(opdata->em->bm, &opdata->em->bm->edata, CD_PROP_FLT, opdata->li);
if (opdata->weights)
MEM_freeN(opdata->weights);
+#endif
if (opdata->is_modal) {
EDBM_redo_state_free(&opdata->mesh_backup, NULL, FALSE);
}
@@ -4662,8 +4858,10 @@ static int edbm_bevel_exec(bContext *C, wmOperator *op)
static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
/* TODO make modal keymap (see fly mode) */
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
BevelData *opdata;
float mlen[2];
+ float center_3d[3];
if (!edbm_bevel_init(C, op, TRUE)) {
return OPERATOR_CANCELLED;
@@ -4672,7 +4870,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
opdata = op->customdata;
/* initialize mouse values */
- if (!calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter)) {
+ if (!calculateTransformCenter(C, V3D_CENTROID, center_3d, opdata->mcenter)) {
/* in this case the tool will likely do nothing,
* ideally this will never happen and should be checked for above */
opdata->mcenter[0] = opdata->mcenter[1] = 0;
@@ -4680,6 +4878,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
mlen[0] = opdata->mcenter[0] - event->mval[0];
mlen[1] = opdata->mcenter[1] - event->mval[1];
opdata->initial_length = len_v2(mlen);
+ opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
edbm_bevel_update_header(op, C);
@@ -4693,12 +4892,66 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
+static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event)
+{
+ BevelData *opdata = op->customdata;
+#ifdef NEW_BEVEL
+ int use_dist = TRUE;
+#else
+ int use_dist = RNA_boolean_get(op->ptr, "use_dist");
+#endif
+ float mdiff[2];
+ float factor;
+
+ mdiff[0] = opdata->mcenter[0] - event->mval[0];
+ mdiff[1] = opdata->mcenter[1] - event->mval[1];
+
+ if (use_dist) {
+ factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size;
+ }
+ else {
+ factor = (len_v2(mdiff) - MVAL_PIXEL_MARGIN) / opdata->initial_length;
+ factor = factor - 1.0f; /* a different kind of buffer where nothing happens */
+ }
+
+ /* Fake shift-transform... */
+ if (event->shift) {
+ if (opdata->shift_factor < 0.0f)
+ opdata->shift_factor = RNA_float_get(op->ptr, "percent");
+ factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor;
+ }
+ else if (opdata->shift_factor >= 0.0f)
+ opdata->shift_factor = -1.0f;
+
+ /* clamp differently based on distance/factor */
+ if (use_dist) {
+ if (factor < 0.0f) factor = 0.0f;
+ }
+ else {
+ CLAMP(factor, 0.0f, 1.0f);
+ }
+
+ return factor;
+}
+
static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
{
BevelData *opdata = op->customdata;
+ int segments = RNA_int_get(op->ptr, "segments");
if (event->val == KM_PRESS) {
/* Try to handle numeric inputs... */
+#ifdef NEW_BEVEL
+ float value;
+
+ if (handleNumInput(&opdata->num_input, event)) {
+ applyNumInput(&opdata->num_input, &value);
+ RNA_float_set(op->ptr, "offset", value);
+ edbm_bevel_calc(C, op);
+ edbm_bevel_update_header(op, C);
+ return OPERATOR_RUNNING_MODAL;
+ }
+#else
float factor;
if (handleNumInput(&opdata->num_input, event)) {
@@ -4710,6 +4963,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
edbm_bevel_update_header(op, C);
return OPERATOR_RUNNING_MODAL;
}
+#endif
}
switch (event->type) {
@@ -4720,26 +4974,12 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
case MOUSEMOVE:
if (!hasNumInput(&opdata->num_input)) {
- float factor;
- float mdiff[2];
-
- mdiff[0] = opdata->mcenter[0] - event->mval[0];
- mdiff[1] = opdata->mcenter[1] - event->mval[1];
-
- factor = opdata->initial_length / -len_v2(mdiff) + 1.0f;
-
- /* Fake shift-transform... */
- if (event->shift) {
- if (opdata->shift_factor < 0.0f)
- opdata->shift_factor = RNA_float_get(op->ptr, "percent");
- factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor;
- }
- else if (opdata->shift_factor >= 0.0f)
- opdata->shift_factor = -1.0f;
-
- CLAMP(factor, 0.0f, 1.0f);
-
+ const float factor = edbm_bevel_mval_factor(op, event);
+#ifdef NEW_BEVEL
+ RNA_float_set(op->ptr, "offset", factor);
+#else
RNA_float_set(op->ptr, "percent", factor);
+#endif
edbm_bevel_calc(C, op);
edbm_bevel_update_header(op, C);
@@ -4753,6 +4993,28 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
edbm_bevel_exit(C, op);
return OPERATOR_FINISHED;
+#ifdef NEW_BEVEL
+ case WHEELUPMOUSE: /* change number of segments */
+ if (event->val == KM_RELEASE)
+ break;
+
+ segments++;
+ RNA_int_set(op->ptr, "segments", segments);
+ edbm_bevel_calc(C, op);
+ edbm_bevel_update_header(op, C);
+ break;
+
+ case WHEELDOWNMOUSE: /* change number of segments */
+ if (event->val == KM_RELEASE)
+ break;
+
+ segments = max_ii(segments - 1, 1);
+ RNA_int_set(op->ptr, "segments", segments);
+ edbm_bevel_calc(C, op);
+ edbm_bevel_update_header(op, C);
+ break;
+
+#else
case EKEY:
if (event->val == KM_PRESS) {
int use_even = RNA_boolean_get(op->ptr, "use_even");
@@ -4768,10 +5030,16 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
int use_dist = RNA_boolean_get(op->ptr, "use_dist");
RNA_boolean_set(op->ptr, "use_dist", !use_dist);
+ {
+ const float factor = edbm_bevel_mval_factor(op, event);
+ RNA_float_set(op->ptr, "percent", factor);
+ }
+
edbm_bevel_calc(C, op);
edbm_bevel_update_header(op, C);
}
break;
+#endif
}
return OPERATOR_RUNNING_MODAL;
@@ -4794,12 +5062,18 @@ void MESH_OT_bevel(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+#ifdef NEW_BEVEL
+ RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Offset", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
+#else
+ /* take note, used as a factor _and_ a distance depending on 'use_dist' */
RNA_def_float(ot->srna, "percent", 0.0f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f);
/* XXX, disabled for 2.63 release, needs to work much better without overlap before we can give to users. */
/* RNA_def_int(ot->srna, "recursion", 1, 1, 50, "Recursion Level", "Recursion Level", 1, 8); */
RNA_def_boolean(ot->srna, "use_even", FALSE, "Even", "Calculate evenly spaced bevel");
RNA_def_boolean(ot->srna, "use_dist", FALSE, "Distance", "Interpret the percent in blender units");
+#endif
}
@@ -4858,8 +5132,9 @@ typedef struct {
float old_depth;
int mcenter[2];
int modify_depth;
- int is_modal;
float initial_length;
+ float pixel_size; /* use when mouse input is interpreted as spatial distance */
+ int is_modal;
int shift;
float shift_amount;
BMBackup backup;
@@ -5025,15 +5300,17 @@ static int edbm_inset_exec(bContext *C, wmOperator *op)
static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
InsetData *opdata;
float mlen[2];
+ float center_3d[3];
edbm_inset_init(C, op, TRUE);
opdata = op->customdata;
/* initialize mouse values */
- if (!calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter)) {
+ if (!calculateTransformCenter(C, V3D_CENTROID, center_3d, opdata->mcenter)) {
/* in this case the tool will likely do nothing,
* ideally this will never happen and should be checked for above */
opdata->mcenter[0] = opdata->mcenter[1] = 0;
@@ -5041,6 +5318,7 @@ static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event)
mlen[0] = opdata->mcenter[0] - event->mval[0];
mlen[1] = opdata->mcenter[1] - event->mval[1];
opdata->initial_length = len_v2(mlen);
+ opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
edbm_inset_calc(C, op);
@@ -5060,7 +5338,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
if (handleNumInput(&opdata->num_input, event)) {
applyNumInput(&opdata->num_input, amounts);
- amounts[0] = maxf(amounts[0], 0.0f);
+ amounts[0] = max_ff(amounts[0], 0.0f);
RNA_float_set(op->ptr, "thickness", amounts[0]);
RNA_float_set(op->ptr, "depth", amounts[1]);
@@ -5090,9 +5368,9 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
mdiff[1] = opdata->mcenter[1] - event->mval[1];
if (opdata->modify_depth)
- amount = opdata->old_depth + opdata->initial_length / len_v2(mdiff) - 1.0f;
+ amount = opdata->old_depth + ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size);
else
- amount = opdata->old_thickness - opdata->initial_length / len_v2(mdiff) + 1.0f;
+ amount = opdata->old_thickness - ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size);
/* Fake shift-transform... */
if (opdata->shift)
@@ -5101,7 +5379,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
if (opdata->modify_depth)
RNA_float_set(op->ptr, "depth", amount);
else {
- amount = maxf(amount, 0.0f);
+ amount = max_ff(amount, 0.0f);
RNA_float_set(op->ptr, "thickness", amount);
}
@@ -5299,6 +5577,7 @@ void MESH_OT_wireframe(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_replace", TRUE, "Replace", "Remove original faces");
}
+#ifdef WITH_BULLET
static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -5392,3 +5671,55 @@ void MESH_OT_convex_hull(wmOperatorType *ot)
join_triangle_props(ot);
}
+#endif
+
+static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BMEdit_FromObject(obedit);
+ BMOperator bmop;
+
+ EDBM_op_init(em, &bmop, op, "symmetrize input=%hvef direction=%i",
+ BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"));
+ BMO_op_exec(em->bm, &bmop);
+
+ if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ EDBM_update_generic(C, em, TRUE);
+ EDBM_selectmode_flush(em);
+ return OPERATOR_FINISHED;
+ }
+}
+
+void MESH_OT_symmetrize(struct wmOperatorType *ot)
+{
+ static EnumPropertyItem axis_direction_items[] = {
+ {BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""},
+ {BMO_SYMMETRIZE_POSITIVE_X, "POSITIVE_X", 0, "+X to -X", ""},
+
+ {BMO_SYMMETRIZE_NEGATIVE_Y, "NEGATIVE_Y", 0, "-Y to +Y", ""},
+ {BMO_SYMMETRIZE_POSITIVE_Y, "POSITIVE_Y", 0, "+Y to -Y", ""},
+
+ {BMO_SYMMETRIZE_NEGATIVE_Z, "NEGATIVE_Z", 0, "-Z to +Z", ""},
+ {BMO_SYMMETRIZE_POSITIVE_Z, "POSITIVE_Z", 0, "+Z to -Z", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Symmetrize";
+ ot->description = "Enforce symmetry (both form and topological) across an axis";
+ ot->idname = "MESH_OT_symmetrize";
+
+ /* api callbacks */
+ ot->exec = mesh_symmetrize_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "direction", axis_direction_items,
+ BMO_SYMMETRIZE_NEGATIVE_X,
+ "Direction", "Which sides to copy from and to");
+}