From 70453c578dcdce5577015e1cd7be99d1b810215d Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Thu, 17 Jul 2014 09:20:22 -0400 Subject: Fix T34664: bevel face material can be set in tool and modifier. Now the bevel tool, modifier, and internal operator have a material slot # parameter that the user can set. If left at default of -1, behavior is as current -- bevel face material is taken from the closest original face (this may be ambiguous). If material slot is >= 0, it gives the material slot index number for the material to use. --- source/blender/bmesh/intern/bmesh_opdefines.c | 1 + source/blender/bmesh/operators/bmo_bevel.c | 3 +- source/blender/bmesh/tools/bmesh_bevel.c | 55 +++++++++++++++------------ source/blender/bmesh/tools/bmesh_bevel.h | 3 +- source/blender/editors/mesh/editmesh_bevel.c | 9 ++++- source/blender/makesdna/DNA_modifier_types.h | 3 ++ source/blender/makesrna/intern/rna_modifier.c | 7 ++++ source/blender/modifiers/intern/MOD_bevel.c | 5 ++- 8 files changed, 57 insertions(+), 29 deletions(-) (limited to 'source') diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 7c77302c942..b9da7618df8 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1580,6 +1580,7 @@ static BMOpDefine bmo_bevel_def = { {"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 */ + {"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */ {{'\0'}}, }, /* slots_out */ diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 07a2e674863..213a0830e63 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -40,6 +40,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) 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"); + const int material = BMO_slot_int_get(op->slots_in, "material"); if (offset > 0) { BMOIter siter; @@ -60,7 +61,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) } } - BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, false, NULL, -1); + BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, false, NULL, -1, material); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 634ac510e6c..bd7378f30e9 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -187,6 +187,7 @@ typedef struct BevelParams { bool limit_offset; /* should offsets be limited by collisions? */ const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */ int vertex_group; /* vertex group index, maybe set if vertex_only */ + int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */ } BevelParams; // #pragma GCC diagnostic ignored "-Wpadded" @@ -356,11 +357,12 @@ static BMFace *boundvert_rep_face(BoundVert *v) * Make ngon from verts alone. * Make sure to properly copy face attributes and do custom data interpolation from * corresponding elements of face_arr, if that is non-NULL, else from facerep. + * If mat_nr >= 0 then the material of the face is set to that. * * \note ALL face creation goes through this function, this is important to keep! */ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, - BMFace **face_arr, BMFace *facerep, bool do_interp) + BMFace **face_arr, BMFace *facerep, int mat_nr, bool do_interp) { BMIter iter; BMLoop *l; @@ -395,22 +397,24 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BM_elem_flag_enable(f, BM_ELEM_TAG); } + if (mat_nr >= 0) + f->mat_nr = mat_nr; return f; } static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *facerep, bool do_interp) + BMFace *facerep, int mat_nr, bool do_interp) { BMVert *varr[4] = {v1, v2, v3, v4}; - return bev_create_ngon(bm, varr, v4 ? 4 : 3, NULL, facerep, do_interp); + return bev_create_ngon(bm, varr, v4 ? 4 : 3, NULL, facerep, mat_nr, do_interp); } static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4) + BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr) { BMVert *varr[4] = {v1, v2, v3, v4}; BMFace *farr[4] = {f1, f2, f3, f4}; - return bev_create_ngon(bm, varr, v4 ? 4 : 3, farr, f1, true); + return bev_create_ngon(bm, varr, v4 ? 4 : 3, farr, f1, mat_nr, true); } @@ -490,13 +494,13 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f * one side (f1, arbitrarily), and interpolate them all on that side. * For face data, use f1 (arbitrarily) as face representative. */ static BMFace *bev_create_quad_straddle(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *f1, BMFace *f2, bool is_seam) + BMFace *f1, BMFace *f2, int mat_nr, bool is_seam) { BMFace *f, *facerep; BMLoop *l; BMIter iter; - f = bev_create_quad_tri(bm, v1, v2, v3, v4, f1, false); + f = bev_create_quad_tri(bm, v1, v2, v3, v4, f1, mat_nr, false); if (!f) return NULL; @@ -2500,6 +2504,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv) BMVert *bmv1, *bmv2, *bmv3, *bmv4; BMFace *f, *f2, *f23; BoundVert *vpipe; + int mat_nr = bp->mat_nr; n = bv->vmesh->count; ns = bv->vmesh->seg; @@ -2552,7 +2557,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv) if (odd && k == ns2 && f2 && !v->any_seam) f23 = f2; bev_create_quad_tri_ex(bm, bmv1, bmv2, bmv3, bmv4, - f, f23, f23, f); + f, f23, f23, f, mat_nr); } } } while ((v = v->next) != vm->boundstart); @@ -2589,13 +2594,13 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv) BLI_array_append(vf, v->any_seam ? f : boundvert_rep_face(v)); } while ((v = v->next) != vm->boundstart); f = boundvert_rep_face(vm->boundstart); - bev_create_ngon(bm, vv, BLI_array_count(vv), vf, f, true); + bev_create_ngon(bm, vv, BLI_array_count(vv), vf, f, mat_nr, true); BLI_array_free(vv); } } -static BMFace *bevel_build_poly(BMesh *bm, BevVert *bv) +static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv) { BMFace *f; int n, k; @@ -2625,7 +2630,7 @@ static BMFace *bevel_build_poly(BMesh *bm, BevVert *bv) } } while ((v = v->next) != vm->boundstart); if (n > 2) { - f = bev_create_ngon(bm, vv, n, vf, boundvert_rep_face(v), true); + f = bev_create_ngon(bm, vv, n, vf, boundvert_rep_face(v), bp->mat_nr, true); } else { f = NULL; @@ -2634,12 +2639,12 @@ static BMFace *bevel_build_poly(BMesh *bm, BevVert *bv) return f; } -static void bevel_build_trifan(BMesh *bm, BevVert *bv) +static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv) { BMFace *f; BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1); - f = bevel_build_poly(bm, bv); + f = bevel_build_poly(bp, bm, bv); if (f) { /* we have a polygon which we know starts at the previous vertex, make it into a fan */ @@ -2669,12 +2674,12 @@ static void bevel_build_trifan(BMesh *bm, BevVert *bv) } } -static void bevel_build_quadstrip(BMesh *bm, BevVert *bv) +static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv) { BMFace *f; BLI_assert(bv->selcount == 2); - f = bevel_build_poly(bm, bv); + f = bevel_build_poly(bp, bm, bv); if (f) { /* we have a polygon which we know starts at this vertex, make it into strips */ @@ -2813,16 +2818,16 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) bevel_build_one_wire(bm, bv); break; case M_POLY: - bevel_build_poly(bm, bv); + bevel_build_poly(bp, bm, bv); break; case M_ADJ: bevel_build_rings(bp, bm, bv); break; case M_TRI_FAN: - bevel_build_trifan(bm, bv); + bevel_build_trifan(bp, bm, bv); break; case M_QUAD_STRIP: - bevel_build_quadstrip(bm, bv); + bevel_build_quadstrip(bp, bm, bv); break; } } @@ -3173,7 +3178,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) } if (do_rebuild) { n = BLI_array_count(vv); - f_new = bev_create_ngon(bm, vv, n, NULL, f, true); + f_new = bev_create_ngon(bm, vv, n, NULL, f, -1, true); for (k = 0; k < BLI_array_count(vv_fix); k++) { bev_merge_uvs(bm, vv_fix[k]); @@ -3382,8 +3387,9 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) VMesh *vm1, *vm2; EdgeHalf *e1, *e2; BMEdge *bme1, *bme2; - BMFace *f1, *f2, *f; + BMFace *f1, *f2, *f, *newf; int k, nseg, i1, i2, odd, mid; + int mat_nr = bp->mat_nr; if (!BM_edge_is_manifold(bme)) return; @@ -3422,7 +3428,7 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) vm2 = bv2->vmesh; if (nseg == 1) { - bev_create_quad_straddle(bm, bmv1, bmv2, bmv3, bmv4, f1, f2, e1->is_seam); + newf = bev_create_quad_straddle(bm, bmv1, bmv2, bmv3, bmv4, f1, f2, mat_nr, e1->is_seam); } else { bmv1i = bmv1; @@ -3433,11 +3439,11 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) bmv4i = mesh_vert(vm1, i1, 0, k)->v; bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v; if (odd && k == mid + 1) { - bev_create_quad_straddle(bm, bmv1i, bmv2i, bmv3i, bmv4i, f1, f2, e1->is_seam); + bev_create_quad_straddle(bm, bmv1i, bmv2i, bmv3i, bmv4i, f1, f2, mat_nr, e1->is_seam); } else { f = (k <= mid) ? f1 : f2; - bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f, true); + bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f, mat_nr, true); } bmv1i = bmv4i; bmv2i = bmv3i; @@ -3676,7 +3682,7 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp) void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments, const float profile, const bool vertex_only, const bool use_weights, const bool limit_offset, - const struct MDeformVert *dvert, const int vertex_group) + const struct MDeformVert *dvert, const int vertex_group, const int mat) { BMIter iter; BMVert *v, *v_next; @@ -3694,6 +3700,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, bp.limit_offset = limit_offset; bp.dvert = dvert; bp.vertex_group = vertex_group; + bp.mat_nr = mat; if (bp.pro_super_r < 0.60f) bp.pro_super_r = 0.60f; /* TODO: implement 0 case properly */ diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index 0c088ce0238..52d8faa5401 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -31,6 +31,7 @@ struct MDeformVert; void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments, const float profile, const bool vertex_only, const bool use_weights, - const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group); + const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group, + const int mat); #endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index e25919b7400..a03cfe79b0d 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -146,15 +146,19 @@ static bool edbm_bevel_calc(wmOperator *op) 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"); + int material = RNA_int_get(op->ptr, "material"); /* revert to original mesh */ if (opdata->is_modal) { EDBM_redo_state_restore(opdata->mesh_backup, em, false); } + if (em->ob) + material = CLAMPIS(material, -1, em->ob->totcol - 1); + EDBM_op_init(em, &bmop, op, - "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f", - BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile); + "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f material=%i", + BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, material); BMO_op_exec(em->bm, &bmop); @@ -445,4 +449,5 @@ void MESH_OT_bevel(wmOperatorType *ot) RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8); RNA_def_float(ot->srna, "profile", 0.5f, 0.15f, 1.0f, "Profile", "Controls profile shape (0.5 = round)", 0.15f, 1.0f); RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex only", "Bevel only vertices"); + RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material", "Material for bevel faces (-1 means use adjacent faces)", -1, 100); } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 7c5846e5819..2bd33ae60f2 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -308,6 +308,9 @@ typedef struct BevelModifierData { short val_flags; /* used to interpret the bevel value */ short lim_flags; /* flags to tell the tool how to limit the bevel */ short e_flags; /* flags to direct how edge weights are applied to verts */ + short mat; /* material index if >= 0, else material inherited from surrounding faces */ + short pad; + int pad2; float profile; /* controls profile shape (0->1, .5 is round) */ /* if the MOD_BEVEL_ANGLE is set, this will be how "sharp" an edge must be before it gets beveled */ float bevel_angle; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index a998da661f1..fb7601064cf 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -2239,6 +2239,13 @@ static void rna_def_modifier_bevel(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.15f, 1.0f, 0.05, 2); RNA_def_property_ui_text(prop, "Profile", "The profile shape (0.5 = round)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "material", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "mat"); + RNA_def_property_range(prop, -1, SHRT_MAX); + RNA_def_property_ui_text(prop, "Material", "Material index of generated faces, -1 for automatic"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + } static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index fc65990df20..2de3220e683 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -57,6 +57,7 @@ static void initData(ModifierData *md) bmd->val_flags = MOD_BEVEL_AMT_OFFSET; bmd->lim_flags = 0; bmd->e_flags = 0; + bmd->mat = -1; bmd->profile = 0.5f; bmd->bevel_angle = DEG2RADF(30.0f); bmd->defgrp_name[0] = '\0'; @@ -73,6 +74,7 @@ static void copyData(ModifierData *md, ModifierData *target) tbmd->val_flags = bmd->val_flags; tbmd->lim_flags = bmd->lim_flags; tbmd->e_flags = bmd->e_flags; + tbmd->mat = bmd->mat; tbmd->profile = bmd->profile; tbmd->bevel_angle = bmd->bevel_angle; BLI_strncpy(tbmd->defgrp_name, bmd->defgrp_name, sizeof(tbmd->defgrp_name)); @@ -109,6 +111,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob, 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 mat = CLAMPIS(bmd->mat, -1, ob->totcol - 1); bm = DM_to_bmesh(dm, true); if ((bmd->lim_flags & MOD_BEVEL_VGROUP) && bmd->defgrp_name[0]) @@ -165,7 +168,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob, BM_mesh_bevel(bm, bmd->value, offset_type, bmd->res, bmd->profile, vertex_only, bmd->lim_flags & MOD_BEVEL_WEIGHT, do_clamp, - dvert, vgroup); + dvert, vgroup, mat); result = CDDM_from_bmesh(bm, true); -- cgit v1.2.3