Bevel: Refactor profile type input to use an enum

This will allow the easier addition of a constant radius mode in the
future and some changes in the UI to mirror the recent similar change
from "Only Vertices" to the "Affect" enum.
This commit is contained in:
Hans Goudey 2020-06-22 22:25:55 -04:00
parent 716a8241d3
commit 6703c7f7f1
12 changed files with 208 additions and 124 deletions

View File

@ -5179,7 +5179,7 @@ def km_bevel_modal_map(_params):
("MARK_SHARP_TOGGLE", {"type": 'K', "value": 'PRESS', "any": True}, None),
("OUTER_MITER_CHANGE", {"type": 'O', "value": 'PRESS', "any": True}, None),
("INNER_MITER_CHANGE", {"type": 'I', "value": 'PRESS', "any": True}, None),
("CUSTOM_PROFILE_TOGGLE", {"type": 'Z', "value": 'PRESS', "any": True}, None),
("PROFILE_TYPE_CHANGE", {"type": 'Z', "value": 'PRESS', "any": True}, None),
("VERTEX_MESH_CHANGE", {"type": 'N', "value": 'PRESS', "any": True}, None),
])

View File

@ -747,18 +747,30 @@ class _defs_edit_mesh:
layout.prop(props, "offset_type")
layout.prop(props, "segments")
layout.prop(props, "profile", slider=True)
row = layout.row()
row.prop(props, "profile_type", expand=True)
if props.profile_type == 'SUPERELLIPSE':
layout.prop(props, "profile", text="Shape", slider=True)
if region_type == 'TOOL_HEADER':
layout.popover("TOPBAR_PT_tool_settings_extra", text="...")
else:
extra = True
if extra or region_type != 'TOOL_HEADER':
layout.prop(props, "vertex_only")
layout.prop(props, "clamp_overlap")
layout.prop(props, "loop_slide")
layout.prop(props, "harden_normals")
if extra:
layout.use_property_split = True
layout.use_property_decorate = False
if props.profile_type == 'CUSTOM':
layout.prop(props, "profile", text="Miter Shape", slider=True)
col = layout.column()
col.prop(props, "vertex_only")
col.prop(props, "clamp_overlap")
col.prop(props, "loop_slide")
col.prop(props, "harden_normals")
col = layout.column(heading="Mark")
col.prop(props, "mark_seam", text="Seam")
col.prop(props, "mark_sharp", text="Sharp")
@ -770,8 +782,7 @@ class _defs_edit_mesh:
if props.miter_inner == 'ARC':
layout.prop(props, "spread")
layout.prop(props, "use_custom_profile")
if props.use_custom_profile:
if props.profile_type == 'CUSTOM':
tool_settings = context.tool_settings
layout.template_curveprofile(tool_settings, "custom_bevel_profile_preset")

View File

@ -333,4 +333,18 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
/* Refactor bevel profile type to use an enum. */
if (!DNA_struct_elem_find(fd->filesdna, "BevelModifier", "short", "profile_type")) {
for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Bevel) {
BevelModifierData *bmd = (BevelModifierData *)md;
bool use_custom_profile = bmd->flags & MOD_BEVEL_CUSTOM_PROFILE_DEPRECATED;
bmd->profile_type = use_custom_profile ? MOD_BEVEL_PROFILE_CUSTOM :
MOD_BEVEL_PROFILE_SUPERELLIPSE;
}
}
}
}
}

View File

@ -1728,6 +1728,12 @@ static BMO_FlagSet bmo_enum_bevel_offset_type[] = {
{0, NULL},
};
static BMO_FlagSet bmo_enum_bevel_profile_type[] = {
{BEVEL_PROFILE_SUPERELLIPSE, "SUPERELLIPSE"},
{BEVEL_PROFILE_CUSTOM, "CUSTOM"},
{0, NULL},
};
static BMO_FlagSet bmo_enum_bevel_face_strength_type[] = {
{BEVEL_FACE_STRENGTH_NONE, "NONE"},
{BEVEL_FACE_STRENGTH_NEW, "NEW"},
@ -1760,7 +1766,9 @@ static BMOpDefine bmo_bevel_def = {
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */
{"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */
{"offset_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
bmo_enum_bevel_offset_type}, /* how to measure the offset */
bmo_enum_bevel_offset_type}, /* how to measure the offset */
{"profile_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
bmo_enum_bevel_profile_type}, /* The profile type to use for bevel. */
{"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */
{"profile", BMO_OP_SLOT_FLT}, /* profile shape, 0->1 (.5=>round) */
{"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */
@ -1778,9 +1786,7 @@ static BMOpDefine bmo_bevel_def = {
bmo_enum_bevel_miter_type}, /* outer miter kind */
{"spread", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */
{"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */
{"use_custom_profile", BMO_OP_SLOT_BOOL}, /* Whether to use custom profile feature */
/* the ProfileWiget struct for the custom profile shape */
{"custom_profile", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_STRUCT}},
{"custom_profile", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_STRUCT}}, /* CurveProfile */
{"vmesh_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
bmo_enum_bevel_vmesh_method},
{{'\0'}},

View File

@ -112,6 +112,12 @@ enum {
BEVEL_AMT_ABSOLUTE,
};
/* Bevel profile type */
enum {
BEVEL_PROFILE_SUPERELLIPSE,
BEVEL_PROFILE_CUSTOM,
};
/* Bevel face_strength_mode values: should match face_str mode enum in DNA_modifer_types.h */
enum {
BEVEL_FACE_STRENGTH_NONE,

View File

@ -33,6 +33,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
{
const float offset = BMO_slot_float_get(op->slots_in, "offset");
const int offset_type = BMO_slot_int_get(op->slots_in, "offset_type");
const int profile_type = BMO_slot_int_get(op->slots_in, "profile_type");
const int seg = BMO_slot_int_get(op->slots_in, "segments");
const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only");
const float profile = BMO_slot_float_get(op->slots_in, "profile");
@ -47,7 +48,6 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
const int miter_inner = BMO_slot_int_get(op->slots_in, "miter_inner");
const float spread = BMO_slot_float_get(op->slots_in, "spread");
const float smoothresh = BMO_slot_float_get(op->slots_in, "smoothresh");
const bool use_custom_profile = BMO_slot_bool_get(op->slots_in, "use_custom_profile");
const CurveProfile *custom_profile = BMO_slot_ptr_get(op->slots_in, "custom_profile");
const int vmesh_method = BMO_slot_int_get(op->slots_in, "vmesh_method");
@ -76,6 +76,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
BM_mesh_bevel(bm,
offset,
offset_type,
profile_type,
seg,
profile,
vonly,
@ -93,7 +94,6 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
miter_inner,
spread,
smoothresh,
use_custom_profile,
custom_profile,
vmesh_method);

View File

@ -302,6 +302,8 @@ typedef struct BevelParams {
float offset;
/** How offset is measured; enum defined in bmesh_operators.h. */
int offset_type;
/** Profile type: radius, superellipse, or custom */
int profile_type;
/** Number of segments in beveled edge profile. */
int seg;
/** User profile setting. */
@ -324,9 +326,7 @@ typedef struct BevelParams {
bool mark_sharp;
/** Should we harden normals? */
bool harden_normals;
/** Should we use the custom profiles feature? */
bool use_custom_profile;
char _pad[3];
char _pad[1];
/** The struct used to store the custom profile input. */
const struct CurveProfile *custom_profile;
/** Vertex group array, maybe set if vertex_only. */
@ -1737,7 +1737,7 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
}
}
r = pro->super_r;
if (!bp->use_custom_profile && r == PRO_LINE_R) {
if (bp->profile_type == BEVEL_PROFILE_SUPERELLIPSE && r == PRO_LINE_R) {
map_ok = false;
}
else {
@ -2334,7 +2334,7 @@ static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm)
}
bool miter_profile = false;
bool reverse_profile = false;
if (bp->use_custom_profile) {
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Use the miter profile spacing struct if the default is filled with the custom profile. */
miter_profile = (bndv->is_arc_start || bndv->is_patch_start);
/* Don't bother reversing the profile if it's a miter profile */
@ -2464,7 +2464,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
}
/* For the edges not adjacent to the beveled edge, slide the bevel amount along. */
d = efirst->offset_l_spec;
if (bp->use_custom_profile || bp->profile < 0.25f) {
if (bp->profile_type == BEVEL_PROFILE_CUSTOM || bp->profile < 0.25f) {
d *= sqrtf(2.0f); /* Need to go further along the edge to make room for full profile area. */
}
for (e = e->next; e->next != efirst; e = e->next) {
@ -2496,7 +2496,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
}
else if (vm->count == 3) {
use_tri_fan = true;
if (bp->use_custom_profile) {
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Prevent overhanging edges: use M_POLY if the extra point is planar with the profile. */
bndv = efirst->leftv;
float profile_plane[4];
@ -3831,7 +3831,7 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
copy_v3_v3(co, mesh_vert(vm_in, i, 0, k)->co);
/* Smooth boundary rule. Custom profiles shouldn't be smoothed. */
if (!bp->use_custom_profile) {
if (bp->profile_type != BEVEL_PROFILE_CUSTOM) {
copy_v3_v3(co1, mesh_vert(vm_in, i, 0, k - 1)->co);
copy_v3_v3(co2, mesh_vert(vm_in, i, 0, k + 1)->co);
@ -3850,7 +3850,7 @@ static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm_in)
get_profile_point(bp, &bndv->profile, k, ns_out, co);
/* Smooth if using a non-custom profile. */
if (!bp->use_custom_profile) {
if (bp->profile_type != BEVEL_PROFILE_CUSTOM) {
copy_v3_v3(co1, mesh_vert_canon(vm_out, i, 0, k - 1)->co);
copy_v3_v3(co2, mesh_vert_canon(vm_out, i, 0, k + 1)->co);
@ -4078,7 +4078,7 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
int i, j, k, ns2;
float co[3], coc[3];
if (!bp->use_custom_profile) {
if (bp->profile_type != BEVEL_PROFILE_CUSTOM) {
if (r == PRO_SQUARE_R) {
return make_cube_corner_square(mem_arena, nseg);
}
@ -4162,7 +4162,7 @@ static int tri_corner_test(BevelParams *bp, BevVert *bv)
int in_plane_e = 0;
/* The superellipse snapping of this case isn't helpful with custom profiles enabled. */
if (bp->vertex_only || bp->use_custom_profile) {
if (bp->vertex_only || bp->profile_type == BEVEL_PROFILE_CUSTOM) {
return -1;
}
if (bv->vmesh->count != 3) {
@ -4281,7 +4281,7 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
fullness = bp->pro_spacing.fullness;
sub_v3_v3v3(center_direction, original_vertex, boundverts_center);
if (len_squared_v3(center_direction) > BEVEL_EPSILON_SQ) {
if (bp->use_custom_profile) {
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
fullness *= 2.0f;
madd_v3_v3v3fl(mesh_vert(vm0, 0, 1, 1)->co, negative_fullest, center_direction, fullness);
}
@ -4377,7 +4377,7 @@ static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe)
continue;
}
/* With a custom profile just copy the shape of the profile at each ring. */
if (bp->use_custom_profile) {
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Find both profile vertices that correspond to this point. */
if (i == ipipe1 || i == ipipe2) {
if (n_bndv == 3 && i == ipipe1) {
@ -4832,7 +4832,8 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
odd = ns % 2;
BLI_assert(n_bndv >= 3 && ns > 1);
if (bp->pro_super_r == PRO_SQUARE_R && bv->selcount >= 3 && !odd && !bp->use_custom_profile) {
if (bp->pro_super_r == PRO_SQUARE_R && bv->selcount >= 3 && !odd &&
bp->profile_type != BEVEL_PROFILE_CUSTOM) {
vm1 = square_out_adj_vmesh(bp, bv);
}
else if (vpipe) {
@ -4842,7 +4843,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
vm1 = tri_corner_adj_vmesh(bp, bv);
/* The PRO_SQUARE_IN_R profile has boundary edges that merge
* and no internal ring polys except possibly center ngon. */
if (bp->pro_super_r == PRO_SQUARE_IN_R && !bp->use_custom_profile) {
if (bp->pro_super_r == PRO_SQUARE_IN_R && bp->profile_type != BEVEL_PROFILE_CUSTOM) {
build_square_in_vmesh(bp, bm, bv, vm1);
return;
}
@ -5446,7 +5447,7 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
for (k = 1; k < ns; k++) {
v_weld1 = mesh_vert(bv->vmesh, weld1->index, 0, k)->co;
v_weld2 = mesh_vert(bv->vmesh, weld2->index, 0, ns - k)->co;
if (bp->use_custom_profile) {
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Don't bother with special case profile check from below. */
mid_v3_v3v3(co, v_weld1, v_weld2);
}
@ -6835,7 +6836,7 @@ static float find_profile_fullness(BevelParams *bp)
0.647f, /* 11 */
};
if (bp->use_custom_profile) {
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Set fullness to the average "height" of the profile's sampled points. */
fullness = 0.0f;
for (int i = 0; i < nseg; i++) { /* Don't use the end points. */
@ -7171,6 +7172,7 @@ static void bevel_limit_offset(BevelParams *bp, BMesh *bm)
void BM_mesh_bevel(BMesh *bm,
const float offset,
const int offset_type,
const int profile_type,
const int segments,
const float profile,
const bool vertex_only,
@ -7188,7 +7190,6 @@ void BM_mesh_bevel(BMesh *bm,
const int miter_inner,
const float spread,
const float smoothresh,
const bool use_custom_profile,
const struct CurveProfile *custom_profile,
const int vmesh_method)
{
@ -7222,7 +7223,7 @@ void BM_mesh_bevel(BMesh *bm,
bp.spread = spread;
bp.smoothresh = smoothresh;
bp.face_hash = NULL;
bp.use_custom_profile = use_custom_profile;
bp.profile_type = profile_type;
bp.custom_profile = custom_profile;
bp.vmesh_method = vmesh_method;
@ -7257,13 +7258,13 @@ void BM_mesh_bevel(BMesh *bm,
BLI_memarena_use_calloc(bp.mem_arena);
/* Get the 2D profile point locations from either the superellipse or the custom profile. */
set_profile_spacing(&bp, &bp.pro_spacing, bp.use_custom_profile);
set_profile_spacing(&bp, &bp.pro_spacing, bp.profile_type == BEVEL_PROFILE_CUSTOM);
if (bp.seg > 1) {
bp.pro_spacing.fullness = find_profile_fullness(&bp);
}
/* Get separate non-custom profile samples for the miter profiles if they are needed. */
if (bp.use_custom_profile &&
/* Get separate non-custom profile samples for the miter profiles if they are needed */
if (bp.profile_type == BEVEL_PROFILE_CUSTOM &&
(bp.miter_inner != BEVEL_MITER_SHARP || bp.miter_outer != BEVEL_MITER_SHARP)) {
set_profile_spacing(&bp, &bp.pro_spacing_miter, false);
}
@ -7297,13 +7298,13 @@ void BM_mesh_bevel(BMesh *bm,
}
/* Perhaps do a pass to try to even out widths. */
if (!bp.vertex_only && bp.offset_adjust && bp.offset_type != BEVEL_AMT_PERCENT &&
bp.offset_type != BEVEL_AMT_ABSOLUTE) {
if (!bp.vertex_only && bp.offset_adjust &&
!ELEM(offset_type, BEVEL_AMT_PERCENT, BEVEL_AMT_ABSOLUTE)) {
adjust_offsets(&bp, bm);
}
/* Maintain consistent orientations for the asymmetrical custom profiles. */
if (bp.use_custom_profile) {
if (bp.profile_type == BEVEL_PROFILE_CUSTOM) {
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
regularize_profile_orientation(&bp, e);

View File

@ -27,6 +27,7 @@ struct MDeformVert;
void BM_mesh_bevel(BMesh *bm,
const float offset,
const int offset_type,
const int profile_type,
const int segments,
const float profile,
const bool vertex_only,
@ -44,7 +45,6 @@ void BM_mesh_bevel(BMesh *bm,
const int miter_inner,
const float spread,
const float smoothresh,
const bool use_custom_profile,
const struct CurveProfile *custom_profile,
const int vmesh_method);

View File

@ -121,7 +121,7 @@ enum {
BEV_MODAL_MARK_SHARP_TOGGLE,
BEV_MODAL_OUTER_MITER_CHANGE,
BEV_MODAL_INNER_MITER_CHANGE,
BEV_MODAL_CUSTOM_PROFILE_TOGGLE,
BEV_MODAL_PROFILE_TYPE_CHANGE,
BEV_MODAL_VERTEX_MESH_CHANGE,
};
@ -146,7 +146,7 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
int available_len = sizeof(buf);
Scene *sce = CTX_data_scene(C);
char offset_str[NUM_STR_REP_LEN];
const char *mode_str, *omiter_str, *imiter_str, *vmesh_str;
const char *mode_str, *omiter_str, *imiter_str, *vmesh_str, *profile_type_str;
PropertyRNA *prop;
#define WM_MODALKEY(_id) \
@ -170,6 +170,9 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
prop = RNA_struct_find_property(op->ptr, "offset_type");
RNA_property_enum_name_gettexted(
C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &mode_str);
prop = RNA_struct_find_property(op->ptr, "profile_type");
RNA_property_enum_name_gettexted(
C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &profile_type_str);
prop = RNA_struct_find_property(op->ptr, "miter_outer");
RNA_property_enum_name_gettexted(
C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &omiter_str);
@ -195,7 +198,7 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
"%s: Harden Normals (%s), "
"%s: Mark Seam (%s), "
"%s: Mark Sharp (%s), "
"%s: Custom Profile (%s), "
"%s: Profile Type (%s), "
"%s: Intersection (%s)"),
WM_MODALKEY(BEV_MODAL_CONFIRM),
WM_MODALKEY(BEV_MODAL_CANCEL),
@ -221,8 +224,8 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
WM_bool_as_string(RNA_boolean_get(op->ptr, "mark_seam")),
WM_MODALKEY(BEV_MODAL_MARK_SHARP_TOGGLE),
WM_bool_as_string(RNA_boolean_get(op->ptr, "mark_sharp")),
WM_MODALKEY(BEV_MODAL_CUSTOM_PROFILE_TOGGLE),
WM_bool_as_string(RNA_boolean_get(op->ptr, "use_custom_profile")),
WM_MODALKEY(BEV_MODAL_PROFILE_TYPE_CHANGE),
profile_type_str,
WM_MODALKEY(BEV_MODAL_VERTEX_MESH_CHANGE),
vmesh_str);
@ -327,6 +330,7 @@ static bool edbm_bevel_calc(wmOperator *op)
const float offset = get_bevel_offset(op);
const int offset_type = RNA_enum_get(op->ptr, "offset_type");
const int profile_type = RNA_enum_get(op->ptr, "profile_type");
const int segments = RNA_int_get(op->ptr, "segments");
const float profile = RNA_float_get(op->ptr, "profile");
const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
@ -340,7 +344,6 @@ static bool edbm_bevel_calc(wmOperator *op)
const int miter_outer = RNA_enum_get(op->ptr, "miter_outer");
const int miter_inner = RNA_enum_get(op->ptr, "miter_inner");
const float spread = RNA_float_get(op->ptr, "spread");
const bool use_custom_profile = RNA_boolean_get(op->ptr, "use_custom_profile");
const int vmesh_method = RNA_enum_get(op->ptr, "vmesh_method");
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
@ -364,16 +367,17 @@ static bool edbm_bevel_calc(wmOperator *op)
EDBM_op_init(em,
&bmop,
op,
"bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f "
"clamp_overlap=%b material=%i loop_slide=%b mark_seam=%b mark_sharp=%b "
"harden_normals=%b face_strength_mode=%i "
"miter_outer=%i miter_inner=%i spread=%f smoothresh=%f use_custom_profile=%b "
"custom_profile=%p vmesh_method=%i",
"bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i "
"profile_type=%i profile=%f clamp_overlap=%b material=%i loop_slide=%b "
"mark_seam=%b mark_sharp=%b harden_normals=%b face_strength_mode=%i "
"miter_outer=%i miter_inner=%i spread=%f smoothresh=%f custom_profile=%p "
"vmesh_method=%i",
BM_ELEM_SELECT,
offset,
segments,
vertex_only,
offset_type,
profile_type,
profile,
clamp_overlap,
material,
@ -386,7 +390,6 @@ static bool edbm_bevel_calc(wmOperator *op)
miter_inner,
spread,
me->smoothresh,
use_custom_profile,
opdata->custom_profile,
vmesh_method);
@ -681,7 +684,7 @@ wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf)
0,
"Change inner miter",
"Cycle through inner miter kinds"},
{BEV_MODAL_CUSTOM_PROFILE_TOGGLE, "CUSTOM_PROFILE_TOGGLE", 0, "Toggle custom profile", ""},
{BEV_MODAL_PROFILE_TYPE_CHANGE, "PROFILE_TYPE_CHANGE", 0, "Cycle through profile types", ""},
{BEV_MODAL_VERTEX_MESH_CHANGE,
"VERTEX_MESH_CHANGE",
0,
@ -892,9 +895,13 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
case BEV_MODAL_CUSTOM_PROFILE_TOGGLE: {
bool use_custom_profile = RNA_boolean_get(op->ptr, "use_custom_profile");
RNA_boolean_set(op->ptr, "use_custom_profile", !use_custom_profile);
case BEV_MODAL_PROFILE_TYPE_CHANGE: {
int profile_type = RNA_enum_get(op->ptr, "profile_type");
profile_type++;
if (profile_type > BEVEL_PROFILE_CUSTOM) {
profile_type = BEVEL_PROFILE_SUPERELLIPSE;
}
RNA_enum_set(op->ptr, "profile_type", profile_type);
edbm_bevel_calc(op);
edbm_bevel_update_status_text(C, op);
handled = true;
@ -938,21 +945,12 @@ static void edbm_bevel_ui(bContext *C, wmOperator *op)
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
int profile_type = RNA_enum_get(&ptr, "profile_type");
if (RNA_enum_get(&ptr, "offset_type") == BEVEL_AMT_PERCENT) {
uiItemR(layout, &ptr, "offset_pct", 0, NULL, ICON_NONE);
}
else {
switch (RNA_enum_get(&ptr, "offset_type")) {
case BEVEL_AMT_DEPTH:
offset_name = "Depth";
break;
case BEVEL_AMT_WIDTH:
offset_name = "Width";
break;
case BEVEL_AMT_OFFSET:
offset_name = "Offset";
break;
}
prop = RNA_struct_find_property(op->ptr, "offset_type");
RNA_property_enum_name_gettexted(
C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &offset_name);
@ -972,7 +970,14 @@ static void edbm_bevel_ui(bContext *C, wmOperator *op)
uiItemR(col, &ptr, "harden_normals", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "segments", 0, NULL, ICON_NONE);
uiItemR(layout, &ptr, "profile", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
if (ELEM(profile_type, BEVEL_PROFILE_SUPERELLIPSE, BEVEL_PROFILE_CUSTOM)) {
uiItemR(layout,
&ptr,
"profile",
UI_ITEM_R_SLIDER,
(profile_type == BEVEL_PROFILE_SUPERELLIPSE) ? IFACE_("Shape") : IFACE_("Miter Shape"),
ICON_NONE);
}
uiItemR(layout, &ptr, "material", 0, NULL, ICON_NONE);
uiItemL(layout, "Miter Type:", ICON_NONE);
@ -990,9 +995,11 @@ static void edbm_bevel_ui(bContext *C, wmOperator *op)
row = uiLayoutRow(layout, true);
uiItemR(row, &ptr, "vmesh_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiItemR(layout, &ptr, "use_custom_profile", 0, NULL, ICON_NONE);
if (RNA_boolean_get(&ptr, "use_custom_profile")) {
/* Get an RNA pointer to ToolSettings to give to the curve profile template code */
uiItemL(layout, "Profile Type:", ICON_NONE);
row = uiLayoutRow(layout, true);
uiItemR(row, &ptr, "profile_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
if (profile_type == BEVEL_PROFILE_CUSTOM) {
/* Get an RNA pointer to ToolSettings to give to the curve profile template code. */
Scene *scene = CTX_data_scene(C);
RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
uiTemplateCurveProfile(layout, &toolsettings_ptr, "custom_bevel_profile_preset");
@ -1020,6 +1027,20 @@ void MESH_OT_bevel(wmOperatorType *ot)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem prop_profile_type_items[] = {
{BEVEL_PROFILE_SUPERELLIPSE,
"SUPERELLIPSE",
0,
"Superellipse",
"The profile can be a concave or convex curve"},
{BEVEL_PROFILE_CUSTOM,
"CUSTOM",
0,
"Custom",
"The profile can be any arbitrary path between its endpoints"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem face_strength_mode_items[] = {
{BEVEL_FACE_STRENGTH_NONE, "NONE", 0, "None", "Do not set face strength"},
{BEVEL_FACE_STRENGTH_NEW, "NEW", 0, "New", "Set face strength on new faces only"},
@ -1073,13 +1094,24 @@ void MESH_OT_bevel(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR_XY | OPTYPE_BLOCKING;
/* properties */
RNA_def_enum(
ot->srna, "offset_type", offset_type_items, 0, "Width Type", "What distance Width measures");
RNA_def_enum(ot->srna,
"offset_type",
offset_type_items,
0,
"Width Type",
"The method for determining the size of the bevel");
prop = RNA_def_property(ot->srna, "offset", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_range(prop, 0.0, 1e6);
RNA_def_property_ui_range(prop, 0.0, 100.0, 1, 3);
RNA_def_property_ui_text(prop, "Width", "Bevel amount");
RNA_def_enum(ot->srna,
"profile_type",
prop_profile_type_items,
0,
"Profile Type",
"The type of shape used to rebuild a beveled section");
prop = RNA_def_property(ot->srna, "offset_pct", PROP_FLOAT, PROP_PERCENTAGE);
RNA_def_property_range(prop, 0.0, 100);
RNA_def_property_ui_text(prop, "Width Percent", "Bevel amount for percentage method");
@ -1166,12 +1198,6 @@ void MESH_OT_bevel(wmOperatorType *ot)
0.0f,
100.0f);
RNA_def_boolean(ot->srna,
"use_custom_profile",
false,
"Custom Profile",
"Use a custom profile for the bevel");
RNA_def_enum(ot->srna,
"vmesh_method",
vmesh_method_items,

View File

@ -394,6 +394,8 @@ typedef struct BevelModifierData {
short flags;
/** Used to interpret the bevel value. */
short val_flags;
/** For the type and how we build the bevel's profile. */
short profile_type;
/** Flags to tell the tool how to limit the bevel. */
short lim_flags;
/** Flags to direct how edge weights are applied to verts. */
@ -407,6 +409,7 @@ typedef struct BevelModifierData {
short miter_outer;
/** The method to use for creating >2-way intersections */
short vmesh_method;
char _pad0[2];
/** Controls profile shape (0->1, .5 is round). */
float profile;
/** if the MOD_BEVEL_ANGLE is set,
@ -417,6 +420,7 @@ typedef struct BevelModifierData {
* this will be the name of the vert group, MAX_VGROUP_NAME */
char defgrp_name[64];
char _pad1[4];
/** Curve info for the custom profile */
struct CurveProfile *custom_profile;
@ -429,12 +433,15 @@ enum {
MOD_BEVEL_ANGLE = (1 << 3),
MOD_BEVEL_WEIGHT = (1 << 4),
MOD_BEVEL_VGROUP = (1 << 5),
MOD_BEVEL_CUSTOM_PROFILE = (1 << 7),
/* MOD_BEVEL_SAMPLE_STRAIGHT = (1 << 8), */ /* UNUSED */
/* unused = (1 << 9), */
/* unused = (1 << 10), */
/* unused = (1 << 11), */
/* unused = (1 << 12), */
/* unused = (1 << 6), */
#ifdef DNA_DEPRECATED_ALLOW
MOD_BEVEL_CUSTOM_PROFILE_DEPRECATED = (1 << 7),
#endif
/* unused = (1 << 8), */
/* unused = (1 << 9), */
/* unused = (1 << 10), */
/* unused = (1 << 11), */
/* unused = (1 << 12), */
MOD_BEVEL_OVERLAP_OK = (1 << 13),
MOD_BEVEL_EVEN_WIDTHS = (1 << 14),
MOD_BEVEL_HARDEN_NORMALS = (1 << 15),
@ -449,6 +456,12 @@ enum {
MOD_BEVEL_AMT_ABSOLUTE = 4,
};
/* BevelModifierData->profile_type */
enum {
MOD_BEVEL_PROFILE_SUPERELLIPSE = 0,
MOD_BEVEL_PROFILE_CUSTOM = 1,
};
/* BevelModifierData->edge_flags */
enum {
MOD_BEVEL_MARK_SEAM = (1 << 0),

View File

@ -1163,7 +1163,7 @@ static PointerRNA rna_CollisionModifier_settings_get(PointerRNA *ptr)
static void rna_BevelModifier_update_segments(Main *bmain, Scene *scene, PointerRNA *ptr)
{
BevelModifierData *bmd = (BevelModifierData *)ptr->data;
if (RNA_boolean_get(ptr, "use_custom_profile")) {
if (RNA_enum_get(ptr, "profile_type") == MOD_BEVEL_PROFILE_CUSTOM) {
short segments = (short)RNA_int_get(ptr, "segments");
BKE_curveprofile_initialize(bmd->custom_profile, segments);
}
@ -3956,6 +3956,20 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem prop_profile_type_items[] = {
{MOD_BEVEL_PROFILE_SUPERELLIPSE,
"SUPERELLIPSE",
0,
"Superellipse",
"The profile can be a concave or convex curve"},
{MOD_BEVEL_PROFILE_CUSTOM,
"CUSTOM",
0,
"Custom",
"The profile can be any arbitrary path between its endpoints"},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem prop_harden_normals_items[] = {
{MOD_BEVEL_FACE_STRENGTH_NONE, "FSTR_NONE", 0, "None", "Do not set face strength"},
{MOD_BEVEL_FACE_STRENGTH_NEW, "FSTR_NEW", 0, "New", "Set face strength on new faces only"},
@ -4066,6 +4080,13 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Width Type", "What distance Width measures");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "profile_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "profile_type");
RNA_def_property_enum_items(prop, prop_profile_type_items);
RNA_def_property_ui_text(
prop, "Profile Type", "The type of shape used to rebuild a beveled section");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "profile", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 2);
@ -4125,12 +4146,6 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Spread", "Spread distance for inner miter arcs");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "use_custom_profile", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_BEVEL_CUSTOM_PROFILE);
RNA_def_property_ui_text(
prop, "Custom Profile", "Whether to use a user inputted curve for the bevel's profile");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "custom_profile", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CurveProfile");
RNA_def_property_pointer_sdna(prop, NULL, "custom_profile");

View File

@ -118,6 +118,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
const bool vertex_only = (bmd->flags & MOD_BEVEL_VERT) != 0;
const bool do_clamp = !(bmd->flags & MOD_BEVEL_OVERLAP_OK);
const int offset_type = bmd->val_flags;
const int profile_type = bmd->profile_type;
const float value = bmd->value;
const int mat = CLAMPIS(bmd->mat, -1, ctx->object->totcol - 1);
const bool loop_slide = (bmd->flags & MOD_BEVEL_EVEN_WIDTHS) == 0;
@ -128,7 +129,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
const int miter_outer = bmd->miter_outer;
const int miter_inner = bmd->miter_inner;
const float spread = bmd->spread;
const bool use_custom_profile = (bmd->flags & MOD_BEVEL_CUSTOM_PROFILE);
const int vmesh_method = bmd->vmesh_method;
const bool invert_vgroup = (bmd->flags & MOD_BEVEL_INVERT_VGROUP) != 0;
@ -225,6 +225,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
BM_mesh_bevel(bm,
value,
offset_type,
profile_type,
bmd->res,
bmd->profile,
vertex_only,
@ -242,7 +243,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
miter_inner,
spread,
mesh->smoothresh,
use_custom_profile,
bmd->custom_profile,
vmesh_method);
@ -374,47 +374,39 @@ static void shading_panel_draw(const bContext *C, Panel *panel)
static void profile_panel_draw(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
uiLayout *layout = panel->layout;
int profile_type = RNA_enum_get(&ptr, "profile_type");
uiItemR(layout, &ptr, "profile_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiLayoutSetPropSep(layout, true);
uiItemR(layout, &ptr, "profile", UI_ITEM_R_SLIDER, IFACE_("Shape"), ICON_NONE);
}
if (ELEM(profile_type, MOD_BEVEL_PROFILE_SUPERELLIPSE, MOD_BEVEL_PROFILE_CUSTOM)) {
uiItemR(layout,
&ptr,
"profile",
UI_ITEM_R_SLIDER,
(profile_type == MOD_BEVEL_PROFILE_SUPERELLIPSE) ? IFACE_("Shape") :
IFACE_("Miter Shape"),
ICON_NONE);
static void custom_profile_panel_draw_header(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
uiItemR(layout, &ptr, "use_custom_profile", 0, NULL, ICON_NONE);
}
static void custom_profile_panel_draw(const bContext *C, Panel *panel)
{
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
uiLayout *layout = panel->layout;
uiLayoutSetActive(layout, RNA_boolean_get(&ptr, "use_custom_profile"));
uiTemplateCurveProfile(layout, &ptr, "custom_profile");
if (profile_type == MOD_BEVEL_PROFILE_CUSTOM) {
uiLayout *sub = uiLayoutColumn(layout, false);
uiLayoutSetPropDecorate(sub, false);
uiTemplateCurveProfile(sub, &ptr, "custom_profile");
}
}
}
static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = modifier_panel_register(region_type, eModifierType_Bevel, panel_draw);
PanelType *bevel_profil_panel = modifier_subpanel_register(
modifier_subpanel_register(
region_type, "profile", "Profile", NULL, profile_panel_draw, panel_type);
modifier_subpanel_register(region_type,
"custom",
"",
custom_profile_panel_draw_header,
custom_profile_panel_draw,
bevel_profil_panel);
modifier_subpanel_register(
region_type, "geometry", "Geometry", NULL, geometry_panel_draw, panel_type);
modifier_subpanel_register(