From 1b3b01135475d0f0edbc39e78fbe5da77b836b67 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 11 Jan 2015 18:33:12 +0100 Subject: Transfer data: cleanup: Remove 'vertex_group_transfer_weight' operator. We can now use 'generic' data transfer instead. Note new one is not an exact replacement, it should be able to do everyting old op could do though, and more. --- release/scripts/startup/bl_ui/space_view3d.py | 4 +- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 4 +- source/blender/editors/object/object_intern.h | 1 - source/blender/editors/object/object_ops.c | 1 - source/blender/editors/object/object_vgroup.c | 501 +-------------------- 5 files changed, 7 insertions(+), 504 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 6bd2c4cd9b3..3ee5e17dd08 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1603,7 +1603,9 @@ class VIEW3D_MT_paint_weight(Menu): layout.operator("object.vertex_group_quantize", text="Quantize") layout.operator("object.vertex_group_levels", text="Levels") layout.operator("object.vertex_group_blend", text="Blend") - layout.operator("object.vertex_group_transfer_weight", text="Transfer Weights") + prop = layout.operator("object.data_transfer", text="Transfer Weights") + prop.use_reverse_transfer = True + prop.data_type = 'VGROUP_WEIGHTS' layout.operator("object.vertex_group_limit_total", text="Limit Total") layout.operator("object.vertex_group_fix", text="Fix Deforms") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 7aa80bcd791..9dc720a29f2 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1597,7 +1597,9 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel): col = layout.column() col.operator("paint.weight_gradient") - col.operator("object.vertex_group_transfer_weight", text="Transfer Weights") + prop = col.operator("object.data_transfer", text="Transfer Weights") + prop.use_reverse_transfer = True + prop.data_type = 'VGROUP_WEIGHTS' class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel): diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 207afdf1028..64fddf1b6a1 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -225,7 +225,6 @@ void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot); -void OBJECT_OT_vertex_group_transfer_weight(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy_to_selected(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 5189594c919..15eb9090ce5 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -177,7 +177,6 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_vertex_group_select); WM_operatortype_append(OBJECT_OT_vertex_group_deselect); WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked); - WM_operatortype_append(OBJECT_OT_vertex_group_transfer_weight); WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected); WM_operatortype_append(OBJECT_OT_vertex_group_copy); WM_operatortype_append(OBJECT_OT_vertex_group_normalize); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index a0c5b037c1f..e70281c502b 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -243,31 +243,6 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co return false; } -static bool ed_vgroup_dm_parray_alloc(DerivedMesh *dm, MDeformVert ***dvert_arr, int *dvert_tot) -{ - *dvert_tot = 0; - *dvert_arr = NULL; - - if (dm) { - MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); - - if (dvert) { - int i, totvert = dm->getNumVerts(dm); - - *dvert_tot = totvert; - *dvert_arr = MEM_mallocN(sizeof(void *) * totvert, "vgroup parray from me"); - - for (i = 0; i < totvert; i++) { - (*dvert_arr)[i] = dvert + i; - } - - return true; - } - } - - return false; -} - /** * For use with tools that use ED_vgroup_parray_alloc with \a use_vert_sel == true. * This finds the unselected mirror deform verts and copys the weights to them from the selected. @@ -635,51 +610,6 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) /***********************Start weight transfer (WT)*********************************/ -typedef enum WT_VertexGroupMode { - WT_REPLACE_ACTIVE_VERTEX_GROUP = 1, - WT_REPLACE_ALL_VERTEX_GROUPS = 2 -} WT_VertexGroupMode; - -typedef enum WT_Method { - WT_BY_INDEX = 1, - WT_BY_NEAREST_VERTEX = 2, - WT_BY_NEAREST_FACE = 3, - WT_BY_NEAREST_VERTEX_IN_FACE = 4 -} WT_Method; - -typedef enum WT_ReplaceMode { - WT_REPLACE_ALL_WEIGHTS = 1, - WT_REPLACE_EMPTY_WEIGHTS = 2 -} WT_ReplaceMode; - -static EnumPropertyItem WT_vertex_group_mode_item[] = { - {WT_REPLACE_ACTIVE_VERTEX_GROUP, - "WT_REPLACE_ACTIVE_VERTEX_GROUP", 0, "Active", "Transfer active vertex group from selected to active mesh"}, - {WT_REPLACE_ALL_VERTEX_GROUPS, - "WT_REPLACE_ALL_VERTEX_GROUPS", 0, "All", "Transfer all vertex groups from selected to active mesh"}, - {0, NULL, 0, NULL, NULL} -}; - -static EnumPropertyItem WT_method_item[] = { - {WT_BY_INDEX, - "WT_BY_INDEX", 0, "Vertex index", "Copy for identical meshes"}, - {WT_BY_NEAREST_VERTEX, - "WT_BY_NEAREST_VERTEX", 0, "Nearest vertex", "Copy weight from closest vertex"}, - {WT_BY_NEAREST_FACE, - "WT_BY_NEAREST_FACE", 0, "Nearest face", "Barycentric interpolation from nearest face"}, - {WT_BY_NEAREST_VERTEX_IN_FACE, - "WT_BY_NEAREST_VERTEX_IN_FACE", 0, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"}, - {0, NULL, 0, NULL, NULL} -}; - -static EnumPropertyItem WT_replace_mode_item[] = { - {WT_REPLACE_ALL_WEIGHTS, - "WT_REPLACE_ALL_WEIGHTS", 0, "All", "Overwrite all weights"}, - {WT_REPLACE_EMPTY_WEIGHTS, - "WT_REPLACE_EMPTY_WEIGHTS", 0, "Empty", "Add weights to vertices with no weight"}, - {0, NULL, 0, NULL, NULL} -}; - static EnumPropertyItem WT_vertex_group_select_item[] = { {WT_VGROUP_ACTIVE, "ACTIVE", 0, "Active Group", "The active Vertex Group"}, @@ -755,298 +685,6 @@ static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_act ot->prop = prop; } -/* Copy weight.*/ -static void vgroup_transfer_weight(float *r_weight_dst, const float weight_src, const WT_ReplaceMode replace_mode) -{ - switch (replace_mode) { - case WT_REPLACE_ALL_WEIGHTS: - *r_weight_dst = weight_src; - break; - - case WT_REPLACE_EMPTY_WEIGHTS: - if (*r_weight_dst == 0.0f) { - *r_weight_dst = weight_src; - } - break; - - default: - BLI_assert(0); - break; - } -} - -/* Could be exposed externally by implementing it in header with the rest. - * Simple refactoring will break something. - * For now, naming is ed_ instead of ED_*/ -static bool ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGroup *dg_src, Scene *scene, - WT_Method method, WT_ReplaceMode replace_mode, wmOperator *op) -{ - bDeformGroup *dg_dst; - Mesh *me_dst; - DerivedMesh *dmesh_src; - BVHTreeFromMesh tree_mesh_vertices_src, tree_mesh_faces_src = {NULL}; - MDeformVert **dv_array_src, **dv_array_dst, **dv_src, **dv_dst; - MVert *mv_dst, *mv_src; - MFace *mface_src, *mf; - BVHTreeNearest nearest; - MDeformWeight *dw_dst, *dw_src; - int dv_tot_src, dv_tot_dst, i, v_index, index_dst, index_src, index_nearest, index_nearest_vertex; - unsigned int f_index; - float weight, tmp_weight[4], tmp_co[3], normal[3], tmp_mat[4][4], dist_v1, dist_v2, dist_v3, dist_v4; - const int use_vert_sel = vertex_group_use_vert_sel(ob_dst); - bool is_dg_dst_new = false; - - /* Ensure vertex group on target.*/ - if ((dg_dst = defgroup_find_name(ob_dst, dg_src->name)) == NULL) { - dg_dst = BKE_defgroup_new(ob_dst, dg_src->name); - is_dg_dst_new = true; - } - - /* Get meshes.*/ - dmesh_src = mesh_get_derived_final(scene, ob_src, CD_MASK_BAREMESH | CD_MASK_MDEFORMVERT); - me_dst = ob_dst->data; - - /* Get vertex group array from source mesh */ - if (!ed_vgroup_dm_parray_alloc(dmesh_src, &dv_array_src, &dv_tot_src)) { - BKE_report(op->reports, RPT_ERROR, "Transfer failed (source mesh does not have any vertex groups)"); - return false; - } - - /* Create data in memory when nothing there.*/ - if (!me_dst->dvert) BKE_object_defgroup_data_create(&me_dst->id); - - /* Get vertex group for destination mesh */ - ED_vgroup_parray_alloc(&me_dst->id, &dv_array_dst, &dv_tot_dst, use_vert_sel); - - /* Get indexes of vertex groups.*/ - index_src = BLI_findindex(&ob_src->defbase, dg_src); - index_dst = BLI_findindex(&ob_dst->defbase, dg_dst); - - /* Get vertices.*/ - mv_dst = me_dst->mvert; - mv_src = dmesh_src->getVertArray(dmesh_src); - - /* Prepare transformation matrix.*/ - invert_m4_m4(ob_src->imat, ob_src->obmat); - mul_m4_m4m4(tmp_mat, ob_src->imat, ob_dst->obmat); - - /* Clear weights.*/ - if (replace_mode == WT_REPLACE_ALL_WEIGHTS) { - for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++) { - - if (*dv_dst == NULL) continue; - - dw_dst = defvert_find_index(*dv_dst, index_dst); - /* Remove vertex from group.*/ - if (dw_dst) defvert_remove_group(*dv_dst, dw_dst); - } - } - - switch (method) { - - case WT_BY_INDEX: - /* Check if indices are matching, delete and return if not.*/ - if (ob_dst == ob_src || dv_tot_dst == 0 || dv_tot_dst != dv_tot_src || - dv_array_src == NULL || dv_array_dst == NULL) - { - if (is_dg_dst_new) { - BKE_object_defgroup_remove(ob_dst, dg_dst); - } - - if (dv_array_src) MEM_freeN(dv_array_src); - if (dv_array_dst) MEM_freeN(dv_array_dst); - dmesh_src->release(dmesh_src); - BKE_report(op->reports, RPT_ERROR, "Transfer failed (indices are not matching)"); - return false; - } - - /* Loop through the vertices.*/ - for (i = 0, dv_src = dv_array_src, dv_dst = dv_array_dst; - i < me_dst->totvert; - i++, dv_dst++, dv_src++, mv_src++, mv_dst++) - { - - if (*dv_dst == NULL) { - continue; - } - - /* Copy weight.*/ - dw_src = defvert_find_index(*dv_src, index_src); - if (dw_src && dw_src->weight) { - dw_dst = defvert_verify_index(*dv_dst, index_dst); - vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode); - } - } - break; - - case WT_BY_NEAREST_VERTEX: - /* Make node tree.*/ - bvhtree_from_mesh_verts(&tree_mesh_vertices_src, dmesh_src, FLT_EPSILON, 2, 6); - - /* Loop trough vertices.*/ - for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { - - if (*dv_dst == NULL) { - continue; - } - - /* Reset nearest.*/ - nearest.dist_sq = FLT_MAX; - /* It is faster to start searching at the top of the tree instead of previous search result.*/ - nearest.index = -1; - - /* Transform into target space.*/ - mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); - - /* Node tree accelerated search for closest vetex.*/ - BLI_bvhtree_find_nearest(tree_mesh_vertices_src.tree, tmp_co, - &nearest, tree_mesh_vertices_src.nearest_callback, &tree_mesh_vertices_src); - - /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are - * overwritten prior to this. See the "Clear weights." step above.*/ - dw_src = defvert_find_index(dv_array_src[nearest.index], index_src); - if (dw_src && dw_src->weight) { - dw_dst = defvert_verify_index(*dv_dst, index_dst); - vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode); - } - } - - /* Free memory.*/ - free_bvhtree_from_mesh(&tree_mesh_vertices_src); - break; - - case WT_BY_NEAREST_FACE: - /* Get faces.*/ - DM_ensure_tessface(dmesh_src); - mface_src = dmesh_src->getTessFaceArray(dmesh_src); - - /* Make node tree.*/ - bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6); - - /* Loop through the vertices.*/ - for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { - - if (*dv_dst == NULL) { - continue; - } - - /* Reset nearest.*/ - nearest.dist_sq = FLT_MAX; - /* It is faster to start searching at the top of the tree instead of previous search result.*/ - nearest.index = -1; - - /* Transform into target space.*/ - mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); - - /* Node tree accelerated search for closest face.*/ - BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co, - &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src); - index_nearest = nearest.index; - - /* Project onto face.*/ - mf = &mface_src[index_nearest]; - normal_tri_v3(normal, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co); - project_v3_plane(tmp_co, normal, mv_src[mf->v1].co); - - /* Interpolate weights over face.*/ - interp_weights_face_v3(tmp_weight, - mv_src[mf->v1].co, - mv_src[mf->v2].co, - mv_src[mf->v3].co, - mf->v4 ? mv_src[mf->v4].co : NULL, - tmp_co); - - /* Get weights from face.*/ - f_index = mf->v4 ? 3 : 2; - weight = 0.0f; - do { - v_index = (&mf->v1)[f_index]; - weight += tmp_weight[f_index] * defvert_find_weight(dv_array_src[v_index], index_src); - } while (f_index--); - - /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are - * overwritten prior to this. See the "Clear weights." step above.*/ - if (weight > 0.0f) { - dw_dst = defvert_verify_index(*dv_dst, index_dst); - vgroup_transfer_weight(&dw_dst->weight, weight, replace_mode); - } - } - - /* Free memory.*/ - free_bvhtree_from_mesh(&tree_mesh_faces_src); - break; - - case WT_BY_NEAREST_VERTEX_IN_FACE: - /* Get faces.*/ - DM_ensure_tessface(dmesh_src); - mface_src = dmesh_src->getTessFaceArray(dmesh_src); - - /* Make node tree.*/ - bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6); - - /* Loop through the vertices.*/ - for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { - - if (*dv_dst == NULL) { - continue; - } - - /* Reset nearest.*/ - nearest.dist_sq = FLT_MAX; - /* It is faster to start searching at the top of the tree instead of previous search result.*/ - nearest.index = -1; - - /* Transform into target space.*/ - mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); - - /* Node tree accelerated search for closest face.*/ - BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co, - &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src); - index_nearest = nearest.index; - - /* Get distances.*/ - mf = &mface_src[index_nearest]; - dist_v1 = len_squared_v3v3(tmp_co, mv_src[mf->v1].co); - dist_v2 = len_squared_v3v3(tmp_co, mv_src[mf->v2].co); - dist_v3 = len_squared_v3v3(tmp_co, mv_src[mf->v3].co); - - /* Get closest vertex.*/ - f_index = mf->v4 ? 3 : 2; - if (dist_v1 < dist_v2 && dist_v1 < dist_v3) index_nearest_vertex = mf->v1; - else if (dist_v2 < dist_v3) index_nearest_vertex = mf->v2; - else index_nearest_vertex = mf->v3; - if (f_index == 3) { - dist_v4 = len_squared_v3v3(tmp_co, mv_src[mf->v4].co); - if (dist_v4 < dist_v1 && dist_v4 < dist_v2 && dist_v4 < dist_v3) { - index_nearest_vertex = mf->v4; - } - } - - /* Copy weight that are not NULL including weight value 0. In relevant cases, existing weights are - * overwritten prior to this. See the "Clear weights." step above.*/ - dw_src = defvert_find_index(dv_array_src[index_nearest_vertex], index_src); - if (dw_src && dw_src->weight) { - dw_dst = defvert_verify_index(*dv_dst, index_dst); - vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode); - } - } - - /* Free memory.*/ - free_bvhtree_from_mesh(&tree_mesh_faces_src); - break; - - default: - BLI_assert(0); - break; - } - - /* Free memory.*/ - if (dv_array_src) MEM_freeN(dv_array_src); - if (dv_array_dst) MEM_freeN(dv_array_dst); - dmesh_src->release(dmesh_src); - - return true; -} /***********************End weight transfer (WT)***********************************/ @@ -2657,7 +2295,7 @@ static int vertex_group_mesh_poll(bContext *C) ob->defbase.first); } -static int vertex_group_mesh_supported_poll(bContext *C) +static int UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; @@ -3539,143 +3177,6 @@ void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - Object *ob_act = CTX_data_active_object(C); - - bDeformGroup *dg_act = BLI_findlink(&ob_act->defbase, (ob_act->actdef - 1)); - char dg_act_name[MAX_VGROUP_NAME]; /* may be freed so copy */ - - int fail = 0; - bool changed = false; - - WT_VertexGroupMode vertex_group_mode = RNA_enum_get(op->ptr, "group_select_mode"); - WT_Method method = RNA_enum_get(op->ptr, "method"); - WT_ReplaceMode replace_mode = RNA_enum_get(op->ptr, "replace_mode"); - - if (vertex_group_mode == WT_REPLACE_ACTIVE_VERTEX_GROUP) { - if (!dg_act) { - BKE_report(op->reports, RPT_WARNING, "Failed, active object has no active groups"); - return OPERATOR_FINISHED; /* to get the chance to make changes in the redo panel*/ - } - } - - if (dg_act) { - BLI_strncpy(dg_act_name, dg_act->name, sizeof(dg_act_name)); - } - - /* Macro to loop through selected objects and perform operation depending on function, option and method.*/ - CTX_DATA_BEGIN (C, Object *, ob_src, selected_editable_objects) - { - if (ob_act != ob_src) { - - if (BLI_listbase_is_empty(&ob_src->defbase)) { - BKE_reportf(op->reports, RPT_WARNING, - "Skipping object '%s' it has no vertex groups", ob_src->id.name + 2); - continue; - } - else if (ob_src->type != OB_MESH) { - /* armatures can be in pose mode so ignore them */ - if (ob_src->type != OB_ARMATURE) { - BKE_reportf(op->reports, RPT_WARNING, - "Skipping object '%s' only copying from meshes is supported", ob_src->id.name + 2); - } - continue; - } - - switch (vertex_group_mode) { - - case WT_REPLACE_ACTIVE_VERTEX_GROUP: - { - bDeformGroup *dg_src; - dg_src = defgroup_find_name(ob_src, dg_act_name); - - if (dg_src == NULL) { - BKE_reportf(op->reports, RPT_WARNING, - "Skipping object '%s' no group '%s' found", ob_src->id.name + 2, dg_act_name); - continue; - } - - if (ed_vgroup_transfer_weight(ob_act, ob_src, dg_src, scene, method, replace_mode, op)) { - changed = true; - } - else { - fail++; - } - break; - } - case WT_REPLACE_ALL_VERTEX_GROUPS: - { - bDeformGroup *dg_src; - for (dg_src = ob_src->defbase.first; dg_src; dg_src = dg_src->next) { - if (ed_vgroup_transfer_weight(ob_act, ob_src, dg_src, scene, method, replace_mode, op)) { - changed = true; - } - else { - fail++; - } - } - break; - } - default: - BLI_assert(0); - break; - } - } - } - CTX_DATA_END; - - if (changed) { - - /* possible the active vertex group changed because of adding/removing */ - /* note!, dg_act may be realloc'd, only check its not NULL */ - if (dg_act) { - ED_vgroup_select_by_name(ob_act, dg_act_name); - } - else { - ED_vgroup_sync_from_pose(ob_act); - } - - /* Event notifiers for correct display of data.*/ - - - DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_act); /* for buttons */ - WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_act); - return OPERATOR_FINISHED; - } - else { - if (BLI_listbase_is_empty(&op->reports->list)) { - BKE_report(op->reports, RPT_WARNING, "Failed, no other selected objects with vertex groups found"); - } - - return OPERATOR_FINISHED; /* to get the chance to make changes in the redo panel */ - } -} - -/* transfers weight from active to selected */ -void OBJECT_OT_vertex_group_transfer_weight(wmOperatorType *ot) -{ - /* Identifiers.*/ - ot->name = "Transfer Weights"; - ot->idname = "OBJECT_OT_vertex_group_transfer_weight"; - ot->description = "Transfer weight paint to active from selected mesh"; - - /* API callbacks.*/ - ot->poll = vertex_group_mesh_supported_poll; - ot->exec = vertex_group_transfer_weight_exec; - - /* Flags.*/ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* Properties.*/ - /* TODO, use vgroup_operator_subset_select_props for group_select_mode */ - ot->prop = RNA_def_enum(ot->srna, "group_select_mode", WT_vertex_group_mode_item, WT_REPLACE_ALL_VERTEX_GROUPS, "Group", ""); - ot->prop = RNA_def_enum(ot->srna, "method", WT_method_item, WT_BY_NEAREST_FACE, "Method", ""); - ot->prop = RNA_def_enum(ot->srna, "replace_mode", WT_replace_mode_item, WT_REPLACE_ALL_WEIGHTS, "Replace", ""); -} - static int set_active_group_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); -- cgit v1.2.3