Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/mesh/editmesh_tools.c
| Context not available. | |||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ||||
| } | } | ||||
| #include "BLI_pe.h" | |||||
| #include "bmesh_tools.h" | |||||
| #include "DNA_scene_types.h" | |||||
| /* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/ | /* BMESH_TODO this should be properly encapsulated in a bmop. but later.*/ | ||||
| static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) | static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Context not available. | |||||
| Mesh *me = obedit->data; | Mesh *me = obedit->data; | ||||
| Key *key = me->key; | Key *key = me->key; | ||||
| KeyBlock *kb = NULL; | KeyBlock *kb = NULL; | ||||
| BMEditMesh *em = me->edit_btmesh; | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| BMVert *eve; | BMVert *eve; | ||||
| BMIter iter; | BMIter iter; | ||||
| float co[3], *sco; | float co[3], *sco; | ||||
| int totshape; | |||||
| float cosum = 0.0f; | |||||
| int a = 0, totshape = 0; | |||||
| float *factors = NULL; | |||||
| float *dists = NULL; | |||||
| float transform_mtx[3][3]; | |||||
| float buffer_mtx[3][3]; | |||||
| const float blend = RNA_float_get(op->ptr, "blend"); | const float blend = RNA_float_get(op->ptr, "blend"); | ||||
| const int shape = RNA_enum_get(op->ptr, "shape"); | const int shape = RNA_enum_get(op->ptr, "shape"); | ||||
| const bool use_add = RNA_boolean_get(op->ptr, "add"); | const bool use_add = RNA_boolean_get(op->ptr, "add"); | ||||
| const bool use_prop = RNA_boolean_get(op->ptr, "prop_enabled"); | |||||
| const float prop_dist = RNA_float_get(op->ptr, "prop_dist"); | |||||
| const int prop_mode = RNA_enum_get(op->ptr, "prop_mode"); | |||||
| /* sanity check */ | /* sanity check */ | ||||
| totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY); | totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY); | ||||
| Context not available. | |||||
| if (key) { | if (key) { | ||||
| kb = BLI_findlink(&key->block, shape); | kb = BLI_findlink(&key->block, shape); | ||||
| } | } | ||||
| if (use_prop) { | |||||
| if (!factors || !dists) { | |||||
| factors = MEM_mallocN(sizeof(float) * em->bm->totvert, "Blend from Shape PE factors"); | |||||
| dists = MEM_mallocN(sizeof(float) * em->bm->totvert, "Blend from Shape PE dists"); | |||||
| } | |||||
| copy_m3_m4(transform_mtx, obedit->obmat); | |||||
| pseudoinverse_m3_m3(buffer_mtx, transform_mtx, PSEUDOINVERSE_EPSILON); | |||||
| /* bmesh transparently reflects the current shapekey */ | |||||
| BM_calc_connectivity_distance(em->bm, buffer_mtx, dists); | |||||
| BLI_pe_compute_factors(em->bm->totvert, dists, factors, prop_dist, prop_mode); | |||||
| } | |||||
| /* perform blending on selected vertices*/ | /* perform blending on selected vertices*/ | ||||
| BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { | BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, a) { | ||||
| if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) | if (use_prop) { | ||||
| if (factors[a] <= 0.0001f) continue; | |||||
| if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) continue; | |||||
| } | |||||
| else if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN) || !BM_elem_flag_test(eve, BM_ELEM_SELECT)) | |||||
| continue; | continue; | ||||
| /* get coordinates of shapekey we're blending from */ | /* get coordinates of shapekey we're blending from */ | ||||
| sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape); | sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape); | ||||
| copy_v3_v3(co, sco); | copy_v3_v3(co, sco); | ||||
| Context not available. | |||||
| float *rco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative); | float *rco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative); | ||||
| sub_v3_v3v3(co, co, rco); | sub_v3_v3v3(co, co, rco); | ||||
| } | } | ||||
| if (use_prop) | |||||
| madd_v3_v3fl(eve->co, co, blend); | madd_v3_v3fl(eve->co, co, blend * factors[a]); | ||||
| else | |||||
| madd_v3_v3fl(eve->co, co, blend); | |||||
| } | } | ||||
| else { | else { | ||||
| /* in blend mode, we interpolate to the shape key */ | /* in blend mode, we interpolate to the shape key */ | ||||
| interp_v3_v3v3(eve->co, eve->co, co, blend); | if (use_prop) | ||||
| interp_v3_v3v3(eve->co, eve->co, co, blend * factors[a]); | |||||
| else | |||||
| interp_v3_v3v3(eve->co, eve->co, co, blend); | |||||
| } | } | ||||
| } | } | ||||
| EDBM_update_generic(em, true, false); | if (factors) { | ||||
| MEM_freeN(factors); | |||||
| MEM_freeN(dists); | |||||
| } | |||||
| EDBM_update_generic(em, true, false); | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static EnumPropertyItem *falloff_type_dropdown(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) { | |||||
| EnumPropertyItem *item = NULL; | |||||
| EnumPropertyItem temp = {0}; | |||||
| int totitem = 0; | |||||
| temp.description = NULL; | |||||
| temp.icon = ICON_SMOOTHCURVE; | |||||
| temp.identifier = "SMOOTH"; | |||||
| temp.name = IFACE_("Smooth"); | |||||
| temp.value = PROP_SMOOTH; | |||||
| RNA_enum_item_add(&item, &totitem, &temp); | |||||
| temp.description = NULL; | |||||
| temp.icon = ICON_SPHERECURVE; | |||||
| temp.identifier = "SPHERE"; | |||||
| temp.name = IFACE_("Sphere"); | |||||
| temp.value = PROP_SPHERE; | |||||
| RNA_enum_item_add(&item, &totitem, &temp); | |||||
| temp.description = NULL; | |||||
| temp.icon = ICON_ROOTCURVE; | |||||
| temp.identifier = "ROOT"; | |||||
| temp.name = IFACE_("Root"); | |||||
| temp.value = PROP_ROOT; | |||||
| RNA_enum_item_add(&item, &totitem, &temp); | |||||
| temp.description = NULL; | |||||
| temp.icon = ICON_SHARPCURVE; | |||||
| temp.identifier = "SHARP"; | |||||
| temp.name = IFACE_("Sharp"); | |||||
| temp.value = PROP_SHARP; | |||||
| RNA_enum_item_add(&item, &totitem, &temp); | |||||
| temp.description = NULL; | |||||
| temp.icon = ICON_LINCURVE; | |||||
| temp.identifier = "LINEAR"; | |||||
| temp.name = IFACE_("Linear"); | |||||
| temp.value = PROP_LIN; | |||||
| RNA_enum_item_add(&item, &totitem, &temp); | |||||
| temp.description = NULL; | |||||
| temp.icon = ICON_NOCURVE; | |||||
| temp.identifier = "CONSTANT"; | |||||
| temp.name = IFACE_("Constant"); | |||||
| temp.value = PROP_CONST; | |||||
| RNA_enum_item_add(&item, &totitem, &temp); | |||||
| temp.description = NULL; | |||||
| temp.icon = ICON_RNDCURVE; | |||||
| temp.identifier = "RANDOM"; | |||||
| temp.identifier = "Random"; | |||||
| temp.name = IFACE_("Random"); | |||||
| temp.value = PROP_RANDOM; | |||||
| RNA_enum_item_add(&item, &totitem, &temp); | |||||
| RNA_enum_item_end(&item, &totitem); | |||||
| return item; | |||||
| } | |||||
| static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) | static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | Object *obedit = CTX_data_edit_object(C); | ||||
| Context not available. | |||||
| return item; | return item; | ||||
| } | } | ||||
| static int _blend_from_shape_get_icon_id(int prop_mode) { | |||||
| /* ugleh but pretty fast */ | |||||
| return (ICON_SMOOTHCURVE + prop_mode); | |||||
| } | |||||
| static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op) | static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| uiLayout *layout = op->layout; | uiLayout *layout = op->layout; | ||||
| Context not available. | |||||
| uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA); | uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA); | ||||
| uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE); | uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE); | ||||
| uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE); | uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE); | ||||
| uiItemR(layout, &ptr, "prop_enabled", 0, NULL, ICON_NONE); | |||||
| if (RNA_boolean_get(op->ptr, "prop_enabled")) { | |||||
| uiItemMenuEnumR(layout, op->ptr, "prop_mode", "Proportional falloff", | |||||
| _blend_from_shape_get_icon_id(RNA_enum_get(op->ptr, "prop_mode"))); | |||||
| uiItemR(layout, &ptr, "prop_dist", 0, NULL, ICON_NONE); | |||||
| } | |||||
| } | } | ||||
| void MESH_OT_blend_from_shape(wmOperatorType *ot) | void MESH_OT_blend_from_shape(wmOperatorType *ot) | ||||
| Context not available. | |||||
| RNA_def_enum_funcs(prop, shape_itemf); | RNA_def_enum_funcs(prop, shape_itemf); | ||||
| RNA_def_float(ot->srna, "blend", 1.0f, -FLT_MAX, FLT_MAX, "Blend", "Blending factor", -2.0f, 2.0f); | RNA_def_float(ot->srna, "blend", 1.0f, -FLT_MAX, FLT_MAX, "Blend", "Blending factor", -2.0f, 2.0f); | ||||
| RNA_def_boolean(ot->srna, "add", 1, "Add", "Add rather than blend between shapes"); | RNA_def_boolean(ot->srna, "add", 1, "Add", "Add rather than blend between shapes"); | ||||
| RNA_def_boolean(ot->srna, "prop_enabled", true, "Connected Vertices", "Blend nearly connected vertices propotionally"); | |||||
| RNA_def_float(ot->srna, "prop_dist", 1.0f, -FLT_MIN, FLT_MAX, "Distance", "Proportional editing falloff distance", 0.0001f, 10.0f); | |||||
| prop = RNA_def_enum(ot->srna, "prop_mode", DummyRNA_NULL_items, PROP_SMOOTH, "Falloff", "Proportional falloff modes"); | |||||
| RNA_def_enum_funcs(prop, falloff_type_dropdown); | |||||
| } | } | ||||
| static int edbm_solidify_exec(bContext *C, wmOperator *op) | static int edbm_solidify_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Object *obedit = CTX_data_edit_object(C); | Object *obedit = CTX_data_edit_object(C); | ||||
| Context not available. | |||||