forked from bartvdbraak/blender
Added polished Vertex Weights Panel (properties sidebar)
This commit is contained in:
parent
219f3ea85d
commit
70fd2320c8
@ -65,6 +65,8 @@ float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup);
|
|||||||
float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup);
|
float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup);
|
||||||
|
|
||||||
void defvert_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src);
|
void defvert_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src);
|
||||||
|
void defvert_copy_subset(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src,
|
||||||
|
const bool *vgroup_subset, const int vgroup_tot);
|
||||||
void defvert_copy_index(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const int defgroup);
|
void defvert_copy_index(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const int defgroup);
|
||||||
void defvert_sync(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const bool use_verify);
|
void defvert_sync(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const bool use_verify);
|
||||||
void defvert_sync_mapped(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src,
|
void defvert_sync_mapped(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src,
|
||||||
@ -73,6 +75,8 @@ void defvert_remap(struct MDeformVert *dvert, int *map, const int map_len);
|
|||||||
void defvert_flip(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len);
|
void defvert_flip(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len);
|
||||||
void defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len);
|
void defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len);
|
||||||
void defvert_normalize(struct MDeformVert *dvert);
|
void defvert_normalize(struct MDeformVert *dvert);
|
||||||
|
void defvert_normalize_subset(struct MDeformVert *dvert,
|
||||||
|
const bool *vgroup_subset, const int vgroup_tot);
|
||||||
void defvert_normalize_lock_single(struct MDeformVert *dvert, const int def_nr_lock);
|
void defvert_normalize_lock_single(struct MDeformVert *dvert, const int def_nr_lock);
|
||||||
void defvert_normalize_lock_map(struct MDeformVert *dvert, const bool *lock_flags, const int defbase_tot);
|
void defvert_normalize_lock_map(struct MDeformVert *dvert, const bool *lock_flags, const int defbase_tot);
|
||||||
|
|
||||||
|
@ -80,7 +80,21 @@ bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup)
|
|||||||
return outgroup;
|
return outgroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy & overwrite weights */
|
/* overwrite weights filtered by vgroup_subset
|
||||||
|
* - do nothing if neither are set.
|
||||||
|
* - add destination weight if needed
|
||||||
|
*/
|
||||||
|
void defvert_copy_subset(MDeformVert *dvert_dst, const MDeformVert *dvert_src,
|
||||||
|
const bool *vgroup_subset, const int vgroup_tot)
|
||||||
|
{
|
||||||
|
int defgroup;
|
||||||
|
for (defgroup=0; defgroup < vgroup_tot; defgroup++) {
|
||||||
|
if (vgroup_subset[defgroup]) {
|
||||||
|
defvert_copy_index(dvert_dst, dvert_src, defgroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
|
void defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
|
||||||
{
|
{
|
||||||
if (dvert_dst->totweight == dvert_src->totweight) {
|
if (dvert_dst->totweight == dvert_src->totweight) {
|
||||||
@ -181,6 +195,35 @@ void defvert_remap(MDeformVert *dvert, int *map, const int map_len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as #defvert_normalize but takes a bool array.
|
||||||
|
*/
|
||||||
|
void defvert_normalize_subset(MDeformVert *dvert,
|
||||||
|
const bool *vgroup_subset, const int vgroup_tot)
|
||||||
|
{
|
||||||
|
MDeformWeight *dw;
|
||||||
|
unsigned int i;
|
||||||
|
float tot_weight = 0.0f;
|
||||||
|
|
||||||
|
for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
|
||||||
|
if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
|
||||||
|
tot_weight += dw->weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tot_weight > 0.0f) {
|
||||||
|
float scalar = 1.0f / tot_weight;
|
||||||
|
for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
|
||||||
|
if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) {
|
||||||
|
dw->weight *= scalar;
|
||||||
|
|
||||||
|
/* in case of division errors with very low weights */
|
||||||
|
CLAMP(dw->weight, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void defvert_normalize(MDeformVert *dvert)
|
void defvert_normalize(MDeformVert *dvert)
|
||||||
{
|
{
|
||||||
if (dvert->totweight <= 0) {
|
if (dvert->totweight <= 0) {
|
||||||
|
@ -250,6 +250,7 @@ bool ED_vgroup_object_is_edit_mode(struct Object *ob);
|
|||||||
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode);
|
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode);
|
||||||
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
|
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
|
||||||
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
|
float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
|
||||||
|
void ED_vgroup_vert_active_mirror(struct Object *ob, int def_nr);
|
||||||
|
|
||||||
|
|
||||||
/* mesh_data.c */
|
/* mesh_data.c */
|
||||||
|
@ -65,6 +65,11 @@ struct wmKeyConfig;
|
|||||||
struct wmKeyMap;
|
struct wmKeyMap;
|
||||||
struct wmOperator;
|
struct wmOperator;
|
||||||
struct wmOperatorType;
|
struct wmOperatorType;
|
||||||
|
struct PointerRNA;
|
||||||
|
struct PropertyRNA;
|
||||||
|
struct EnumPropertyItem;
|
||||||
|
|
||||||
|
enum eVGroupSelect;
|
||||||
|
|
||||||
/* object_edit.c */
|
/* object_edit.c */
|
||||||
struct Object *ED_object_context(struct bContext *C); /* context.object */
|
struct Object *ED_object_context(struct bContext *C); /* context.object */
|
||||||
@ -200,21 +205,16 @@ int ED_object_multires_update_totlevels_cb(struct Object *ob, void *totlevel_v);
|
|||||||
/* object_select.c */
|
/* object_select.c */
|
||||||
void ED_object_select_linked_by_id(struct bContext *C, struct ID *id);
|
void ED_object_select_linked_by_id(struct bContext *C, struct ID *id);
|
||||||
|
|
||||||
/* object_vgroup.c */
|
|
||||||
typedef enum eVGroupSelect {
|
|
||||||
WT_VGROUP_ACTIVE = 1,
|
|
||||||
WT_VGROUP_BONE_SELECT = 2,
|
|
||||||
WT_VGROUP_BONE_DEFORM = 3,
|
|
||||||
WT_VGROUP_ALL = 4,
|
|
||||||
} eVGroupSelect;
|
|
||||||
|
|
||||||
#define WT_VGROUP_MASK_ALL \
|
bool *ED_vgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type,
|
||||||
((1 << WT_VGROUP_ACTIVE) | \
|
int *r_vgroup_tot, int *r_subset_count);
|
||||||
(1 << WT_VGROUP_BONE_SELECT) | \
|
|
||||||
(1 << WT_VGROUP_BONE_DEFORM) | \
|
|
||||||
(1 << WT_VGROUP_ALL))
|
|
||||||
|
|
||||||
bool *ED_vgroup_subset_from_select_type(struct Object *ob, eVGroupSelect subset_type, int *r_vgroup_tot, int *r_subset_count);
|
struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
|
||||||
|
const struct bContext *C,
|
||||||
|
struct PointerRNA *ptr,
|
||||||
|
struct PropertyRNA *prop,
|
||||||
|
int *free,
|
||||||
|
const unsigned int selection_mask);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -223,6 +223,11 @@ void OBJECT_OT_vertex_group_mirror(struct wmOperatorType *ot);
|
|||||||
void OBJECT_OT_vertex_group_set_active(struct wmOperatorType *ot);
|
void OBJECT_OT_vertex_group_set_active(struct wmOperatorType *ot);
|
||||||
void OBJECT_OT_vertex_group_sort(struct wmOperatorType *ot);
|
void OBJECT_OT_vertex_group_sort(struct wmOperatorType *ot);
|
||||||
void OBJECT_OT_vertex_group_move(struct wmOperatorType *ot);
|
void OBJECT_OT_vertex_group_move(struct wmOperatorType *ot);
|
||||||
|
void OBJECT_OT_vertex_weight_paste(struct wmOperatorType *ot);
|
||||||
|
void OBJECT_OT_vertex_weight_delete(struct wmOperatorType *ot);
|
||||||
|
void OBJECT_OT_vertex_weight_set_active(struct wmOperatorType *ot);
|
||||||
|
void OBJECT_OT_vertex_weight_normalize_active(struct wmOperatorType *ot);
|
||||||
|
void OBJECT_OT_vertex_weight_copy(struct wmOperatorType *ot);
|
||||||
|
|
||||||
/* object_shapekey.c */
|
/* object_shapekey.c */
|
||||||
void OBJECT_OT_shape_key_add(struct wmOperatorType *ot);
|
void OBJECT_OT_shape_key_add(struct wmOperatorType *ot);
|
||||||
|
@ -195,6 +195,11 @@ void ED_operatortypes_object(void)
|
|||||||
WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
|
WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
|
||||||
WM_operatortype_append(OBJECT_OT_vertex_group_sort);
|
WM_operatortype_append(OBJECT_OT_vertex_group_sort);
|
||||||
WM_operatortype_append(OBJECT_OT_vertex_group_move);
|
WM_operatortype_append(OBJECT_OT_vertex_group_move);
|
||||||
|
WM_operatortype_append(OBJECT_OT_vertex_weight_paste);
|
||||||
|
WM_operatortype_append(OBJECT_OT_vertex_weight_delete);
|
||||||
|
WM_operatortype_append(OBJECT_OT_vertex_weight_set_active);
|
||||||
|
WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active);
|
||||||
|
WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
|
||||||
|
|
||||||
WM_operatortype_append(OBJECT_OT_game_property_new);
|
WM_operatortype_append(OBJECT_OT_game_property_new);
|
||||||
WM_operatortype_append(OBJECT_OT_game_property_remove);
|
WM_operatortype_append(OBJECT_OT_game_property_remove);
|
||||||
|
@ -411,6 +411,239 @@ bool ED_vgroup_copy_array(Object *ob, Object *ob_from)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve)
|
||||||
|
{
|
||||||
|
if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) {
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
BMEditMesh *em = me->edit_btmesh;
|
||||||
|
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||||
|
|
||||||
|
if (cd_dvert_offset != -1) {
|
||||||
|
BMEditSelection *ese = (BMEditSelection *)em->bm->selected.last;
|
||||||
|
|
||||||
|
if (ese && ese->htype == BM_VERT) {
|
||||||
|
BMVert *eve = (BMVert *)ese->ele;
|
||||||
|
if (r_eve) *r_eve = eve;
|
||||||
|
return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_eve) *r_eve = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO, cache flip data to speedup calls within a loop. */
|
||||||
|
static void mesh_defvert_mirror_update_internal(Object *ob,
|
||||||
|
MDeformVert *dvert_dst, MDeformVert *dvert_src,
|
||||||
|
const int def_nr)
|
||||||
|
{
|
||||||
|
if (def_nr == -1) {
|
||||||
|
/* all vgroups, add groups where neded */
|
||||||
|
int flip_map_len;
|
||||||
|
int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
|
||||||
|
defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true);
|
||||||
|
MEM_freeN(flip_map);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* single vgroup */
|
||||||
|
MDeformWeight *dw = defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
|
||||||
|
if (dw) {
|
||||||
|
dw->weight = defvert_find_weight(dvert_src, def_nr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index)
|
||||||
|
{
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
int index = BKE_mesh_mselect_active_get(me, ME_VSEL);
|
||||||
|
if (r_index) *r_index = index;
|
||||||
|
if (index == -1 || me->dvert == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return me->dvert + index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ED_mesh_defvert_mirror_update_em(Object *ob, BMVert *eve, int def_nr, int vidx,
|
||||||
|
const int cd_dvert_offset)
|
||||||
|
{
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
BMEditMesh *em = me->edit_btmesh;
|
||||||
|
BMVert *eve_mirr;
|
||||||
|
|
||||||
|
eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx);
|
||||||
|
|
||||||
|
if (eve_mirr && eve_mirr != eve) {
|
||||||
|
MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
||||||
|
MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
|
||||||
|
mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
|
||||||
|
{
|
||||||
|
int vidx_mirr;
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
if (vidx == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vidx_mirr = mesh_get_x_mirror_vert(ob, vidx);
|
||||||
|
|
||||||
|
if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
|
||||||
|
MDeformVert *dvert_src = &me->dvert[vidx];
|
||||||
|
MDeformVert *dvert_dst = &me->dvert[vidx_mirr];
|
||||||
|
mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MDeformVert *ED_mesh_active_dvert_get_only(Object *ob)
|
||||||
|
{
|
||||||
|
if (ob->type == OB_MESH) {
|
||||||
|
if (ob->mode & OB_MODE_EDIT) {
|
||||||
|
return ED_mesh_active_dvert_get_em(ob, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ED_mesh_active_dvert_get_ob(ob, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use when adjusting the active vertex weight and apply to mirror vertices.
|
||||||
|
*/
|
||||||
|
void ED_vgroup_vert_active_mirror(Object *ob, int def_nr)
|
||||||
|
{
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
BMEditMesh *em = me->edit_btmesh;
|
||||||
|
MDeformVert *dvert_act;
|
||||||
|
|
||||||
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
||||||
|
if (em) {
|
||||||
|
BMVert *eve_act;
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
|
||||||
|
if (dvert_act) {
|
||||||
|
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||||
|
ED_mesh_defvert_mirror_update_em(ob, eve_act, def_nr, -1, cd_dvert_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int v_act;
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
|
||||||
|
if (dvert_act) {
|
||||||
|
ED_mesh_defvert_mirror_update_ob(ob, def_nr, v_act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vgroup_remove_weight(Object *ob, const int def_nr)
|
||||||
|
{
|
||||||
|
MDeformVert *dvert_act;
|
||||||
|
MDeformWeight *dw;
|
||||||
|
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_only(ob);
|
||||||
|
|
||||||
|
dw = defvert_find_index(dvert_act, def_nr);
|
||||||
|
defvert_remove_group(dvert_act, dw);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vgroup_normalize_active(Object *ob, eVGroupSelect subset_type)
|
||||||
|
{
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
BMEditMesh *em = me->edit_btmesh;
|
||||||
|
BMVert *eve_act;
|
||||||
|
int v_act;
|
||||||
|
MDeformVert *dvert_act;
|
||||||
|
int subset_count, vgroup_tot;
|
||||||
|
const bool *vgroup_validmap;
|
||||||
|
|
||||||
|
|
||||||
|
if (em) {
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dvert_act == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
||||||
|
defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot);
|
||||||
|
MEM_freeN((void *)vgroup_validmap);
|
||||||
|
|
||||||
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
||||||
|
if (em) {
|
||||||
|
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||||
|
ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int v_act = BKE_mesh_mselect_active_get(me, ME_VSEL);
|
||||||
|
ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
|
||||||
|
{
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
BMEditMesh *em = me->edit_btmesh;
|
||||||
|
MDeformVert *dvert_act;
|
||||||
|
int i, vgroup_tot, subset_count;
|
||||||
|
const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
||||||
|
|
||||||
|
|
||||||
|
if (em) {
|
||||||
|
BMIter iter;
|
||||||
|
BMVert *eve, *eve_act;
|
||||||
|
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||||
|
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
|
||||||
|
if (dvert_act == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
|
||||||
|
if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve != eve_act) {
|
||||||
|
MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
||||||
|
defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
|
||||||
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
||||||
|
ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MDeformVert *dv;
|
||||||
|
int v_act;
|
||||||
|
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
|
||||||
|
if (dvert_act == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dv = me->dvert;
|
||||||
|
for (i = 0; i < me->totvert; i++, dv++) {
|
||||||
|
if ((me->mvert[i].flag & SELECT) && dv != dvert_act) {
|
||||||
|
defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
|
||||||
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
||||||
|
ED_mesh_defvert_mirror_update_ob(ob, -1, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeN((void *)vgroup_validmap);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************Start weight transfer (WT)*********************************/
|
/***********************Start weight transfer (WT)*********************************/
|
||||||
|
|
||||||
typedef enum WT_VertexGroupMode {
|
typedef enum WT_VertexGroupMode {
|
||||||
@ -470,8 +703,8 @@ static EnumPropertyItem WT_vertex_group_select_item[] = {
|
|||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static EnumPropertyItem *rna_vertex_group_selection_itemf_helper(
|
EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
|
||||||
bContext *C, PointerRNA *UNUSED(ptr),
|
const bContext *C, PointerRNA *UNUSED(ptr),
|
||||||
PropertyRNA *UNUSED(prop), int *free, const unsigned int selection_mask)
|
PropertyRNA *UNUSED(prop), int *free, const unsigned int selection_mask)
|
||||||
{
|
{
|
||||||
Object *ob;
|
Object *ob;
|
||||||
@ -505,13 +738,13 @@ static EnumPropertyItem *rna_vertex_group_selection_itemf_helper(
|
|||||||
static EnumPropertyItem *rna_vertex_group_with_single_itemf(bContext *C, PointerRNA *ptr,
|
static EnumPropertyItem *rna_vertex_group_with_single_itemf(bContext *C, PointerRNA *ptr,
|
||||||
PropertyRNA *prop, int *free)
|
PropertyRNA *prop, int *free)
|
||||||
{
|
{
|
||||||
return rna_vertex_group_selection_itemf_helper(C, ptr, prop, free, WT_VGROUP_MASK_ALL);
|
return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, free, WT_VGROUP_MASK_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static EnumPropertyItem *rna_vertex_group_select_itemf(bContext *C, PointerRNA *ptr,
|
static EnumPropertyItem *rna_vertex_group_select_itemf(bContext *C, PointerRNA *ptr,
|
||||||
PropertyRNA *prop, int *free)
|
PropertyRNA *prop, int *free)
|
||||||
{
|
{
|
||||||
return rna_vertex_group_selection_itemf_helper(C, ptr, prop, free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
|
return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_active)
|
static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_active)
|
||||||
@ -1172,11 +1405,6 @@ bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, i
|
|||||||
*r_vgroup_tot = BLI_countlist(&ob->defbase);
|
*r_vgroup_tot = BLI_countlist(&ob->defbase);
|
||||||
|
|
||||||
switch (subset_type) {
|
switch (subset_type) {
|
||||||
case WT_VGROUP_ALL:
|
|
||||||
vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__);
|
|
||||||
memset(vgroup_validmap, true, *r_vgroup_tot * sizeof(*vgroup_validmap));
|
|
||||||
*r_subset_count = *r_vgroup_tot;
|
|
||||||
break;
|
|
||||||
case WT_VGROUP_ACTIVE:
|
case WT_VGROUP_ACTIVE:
|
||||||
{
|
{
|
||||||
const int def_nr_active = ob->actdef - 1;
|
const int def_nr_active = ob->actdef - 1;
|
||||||
@ -1191,20 +1419,44 @@ bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, i
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WT_VGROUP_BONE_SELECT: {
|
case WT_VGROUP_BONE_SELECT:
|
||||||
|
{
|
||||||
vgroup_validmap = BKE_objdef_selected_get(ob, *r_vgroup_tot, r_subset_count);
|
vgroup_validmap = BKE_objdef_selected_get(ob, *r_vgroup_tot, r_subset_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WT_VGROUP_BONE_DEFORM: {
|
case WT_VGROUP_BONE_DEFORM:
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
vgroup_validmap = BKE_objdef_validmap_get(ob, *r_vgroup_tot);
|
vgroup_validmap = BKE_objdef_validmap_get(ob, *r_vgroup_tot);
|
||||||
*r_subset_count = 0;
|
*r_subset_count = 0;
|
||||||
for (i = 0; i < *r_vgroup_tot; i++) {
|
for (i = 0; i < *r_vgroup_tot; i++) {
|
||||||
if (vgroup_validmap[i])
|
if (vgroup_validmap[i] == true) {
|
||||||
*r_subset_count += 1;
|
*r_subset_count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WT_VGROUP_BONE_DEFORM_OFF:
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
vgroup_validmap = BKE_objdef_validmap_get(ob, *r_vgroup_tot);
|
||||||
|
*r_subset_count = 0;
|
||||||
|
for (i = 0; i < *r_vgroup_tot; i++) {
|
||||||
|
vgroup_validmap[i] = !vgroup_validmap[i];
|
||||||
|
if (vgroup_validmap[i] == true) {
|
||||||
|
*r_subset_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WT_VGROUP_ALL:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__);
|
||||||
|
memset(vgroup_validmap, true, *r_vgroup_tot * sizeof(*vgroup_validmap));
|
||||||
|
*r_subset_count = *r_vgroup_tot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vgroup_validmap;
|
return vgroup_validmap;
|
||||||
@ -1616,7 +1868,8 @@ static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vgroup_levels_subset(Object *ob, bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
|
static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
|
||||||
|
const int UNUSED(subset_count),
|
||||||
const float offset, const float gain)
|
const float offset, const float gain)
|
||||||
{
|
{
|
||||||
MDeformWeight *dw;
|
MDeformWeight *dw;
|
||||||
@ -1746,7 +1999,9 @@ static void vgroup_lock_all(Object *ob, int action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vgroup_invert_subset(Object *ob, bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count), const bool auto_assign, const bool auto_remove)
|
static void vgroup_invert_subset(Object *ob,
|
||||||
|
const bool *vgroup_validmap, const int vgroup_tot,
|
||||||
|
const int UNUSED(subset_count), const bool auto_assign, const bool auto_remove)
|
||||||
{
|
{
|
||||||
MDeformWeight *dw;
|
MDeformWeight *dw;
|
||||||
MDeformVert *dv, **dvert_array = NULL;
|
MDeformVert *dv, **dvert_array = NULL;
|
||||||
@ -3001,10 +3256,9 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
int subset_count, vgroup_tot;
|
int subset_count, vgroup_tot;
|
||||||
|
|
||||||
bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
||||||
vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
|
vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
|
||||||
|
MEM_freeN((void *)vgroup_validmap);
|
||||||
MEM_freeN(vgroup_validmap);
|
|
||||||
|
|
||||||
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||||
@ -3183,10 +3437,9 @@ static int vertex_group_invert_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
int subset_count, vgroup_tot;
|
int subset_count, vgroup_tot;
|
||||||
|
|
||||||
bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
||||||
vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
|
vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
|
||||||
|
MEM_freeN((void *)vgroup_validmap);
|
||||||
MEM_freeN(vgroup_validmap);
|
|
||||||
|
|
||||||
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||||
@ -3291,10 +3544,9 @@ static int vertex_group_clean_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
int subset_count, vgroup_tot;
|
int subset_count, vgroup_tot;
|
||||||
|
|
||||||
bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
||||||
vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
|
vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
|
||||||
|
MEM_freeN((void *)vgroup_validmap);
|
||||||
MEM_freeN(vgroup_validmap);
|
|
||||||
|
|
||||||
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||||
@ -3332,10 +3584,9 @@ static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
int subset_count, vgroup_tot;
|
int subset_count, vgroup_tot;
|
||||||
|
|
||||||
bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
||||||
int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit);
|
int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit);
|
||||||
|
MEM_freeN((void *)vgroup_validmap);
|
||||||
MEM_freeN(vgroup_validmap);
|
|
||||||
|
|
||||||
BKE_reportf(op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot);
|
BKE_reportf(op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot);
|
||||||
|
|
||||||
@ -3832,3 +4083,226 @@ void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
|
|||||||
|
|
||||||
RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
|
RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
|
||||||
|
{
|
||||||
|
MDeformVert *dvert_act;
|
||||||
|
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
BMEditMesh *em = me->edit_btmesh;
|
||||||
|
float weight_act;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (em) {
|
||||||
|
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
||||||
|
BMIter iter;
|
||||||
|
BMVert *eve, *eve_act;
|
||||||
|
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
|
||||||
|
if (dvert_act == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
weight_act = defvert_find_weight(dvert_act, def_nr);
|
||||||
|
|
||||||
|
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
|
||||||
|
if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && (eve != eve_act)) {
|
||||||
|
MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
||||||
|
MDeformWeight *dw = defvert_find_index(dv, def_nr);
|
||||||
|
if (dw) {
|
||||||
|
dw->weight = weight_act;
|
||||||
|
|
||||||
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
||||||
|
ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
||||||
|
ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MDeformVert *dv;
|
||||||
|
int v_act;
|
||||||
|
|
||||||
|
dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
|
||||||
|
if (dvert_act == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
weight_act = defvert_find_weight(dvert_act, def_nr);
|
||||||
|
|
||||||
|
dv = me->dvert;
|
||||||
|
for (i = 0; i < me->totvert; i++, dv++) {
|
||||||
|
if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) {
|
||||||
|
MDeformWeight *dw = defvert_find_index(dv, def_nr);
|
||||||
|
if (dw) {
|
||||||
|
dw->weight = weight_act;
|
||||||
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
||||||
|
ED_mesh_defvert_mirror_update_ob(ob, -1, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me->editflag & ME_EDIT_MIRROR_X) {
|
||||||
|
ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vertex_weight_paste(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Object *ob = ED_object_context(C);
|
||||||
|
const int wg_index = RNA_int_get(op->ptr, "weight_group");
|
||||||
|
vgroup_copy_active_to_sel_single(ob, wg_index);
|
||||||
|
|
||||||
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBJECT_OT_vertex_weight_paste(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
ot->name = "Paste weight to Selected";
|
||||||
|
ot->idname = "OBJECT_OT_vertex_weight_paste";
|
||||||
|
ot->description = "Copy this group's weight to other selected verts";
|
||||||
|
|
||||||
|
prop = RNA_def_int(ot->srna, "weight_group",
|
||||||
|
-1, 0, 0, "Weight Index", "Index of source weight in active Weight Group", 0, 0);
|
||||||
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->poll = vertex_group_poll;
|
||||||
|
ot->exec = vertex_weight_paste;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vertex_weight_delete(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Object *ob = ED_object_context(C);
|
||||||
|
const int wg_index = RNA_int_get(op->ptr, "weight_group");
|
||||||
|
vgroup_remove_weight(ob, wg_index);
|
||||||
|
|
||||||
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBJECT_OT_vertex_weight_delete(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
ot->name = "Delete Weight";
|
||||||
|
ot->idname = "OBJECT_OT_vertex_weight_delete";
|
||||||
|
ot->description = "Delete this weight from the vertex";
|
||||||
|
|
||||||
|
prop = RNA_def_int(ot->srna, "weight_group",
|
||||||
|
-1, 0, 0, "Weight Index", "Index of source weight in active Weight Group", 0, 0);
|
||||||
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->poll = vertex_group_poll;
|
||||||
|
ot->exec = vertex_weight_delete;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vertex_weight_set_active(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Object *ob = ED_object_context(C);
|
||||||
|
const int wg_index = RNA_int_get(op->ptr, "weight_group");
|
||||||
|
|
||||||
|
if (wg_index != -1) {
|
||||||
|
ob->actdef = wg_index + 1;
|
||||||
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBJECT_OT_vertex_weight_set_active(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
ot->name = "Set Active Group";
|
||||||
|
ot->idname = "OBJECT_OT_vertex_weight_set_active";
|
||||||
|
ot->description = "Set as active Vertex Group";
|
||||||
|
|
||||||
|
prop = RNA_def_int(ot->srna, "weight_group",
|
||||||
|
-1, 0, 0, "Weight Index", "Index of source weight in active Weight Group", 0, 0);
|
||||||
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->poll = vertex_group_poll;
|
||||||
|
ot->exec = vertex_weight_set_active;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vertex_weight_normalize_active(bContext *C, wmOperator *UNUSED(op))
|
||||||
|
{
|
||||||
|
Object *ob = ED_object_context(C);
|
||||||
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||||
|
eVGroupSelect subset_type = ts->vgroupsubset;
|
||||||
|
|
||||||
|
vgroup_normalize_active(ob, subset_type);
|
||||||
|
|
||||||
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBJECT_OT_vertex_weight_normalize_active(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
|
||||||
|
ot->name = "Normalize Active";
|
||||||
|
ot->idname = "OBJECT_OT_vertex_weight_normalize_active";
|
||||||
|
ot->description = "Normalize Active Vert Weights";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->poll = vertex_group_poll;
|
||||||
|
ot->exec = vertex_weight_normalize_active;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vertex_weight_copy(bContext *C, wmOperator *UNUSED(op))
|
||||||
|
{
|
||||||
|
Object *ob = ED_object_context(C);
|
||||||
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||||
|
eVGroupSelect subset_type = ts->vgroupsubset;
|
||||||
|
|
||||||
|
vgroup_copy_active_to_sel(ob, subset_type);
|
||||||
|
|
||||||
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBJECT_OT_vertex_weight_copy(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
|
||||||
|
ot->name = "Copy Active";
|
||||||
|
ot->idname = "OBJECT_OT_vertex_weight_copy";
|
||||||
|
ot->description = "Copy weights from Active to selected";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->poll = vertex_group_poll;
|
||||||
|
ot->exec = vertex_weight_copy;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
}
|
||||||
|
@ -830,280 +830,19 @@ static MDeformVert *ED_mesh_active_dvert_get_only(Object *ob)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO, cache flip data to speedup calls within a loop. */
|
|
||||||
static void mesh_defvert_mirror_update_internal(Object *ob,
|
|
||||||
MDeformVert *dvert_dst, MDeformVert *dvert_src,
|
|
||||||
const int def_nr)
|
|
||||||
{
|
|
||||||
if (def_nr == -1) {
|
|
||||||
/* all vgroups, add groups where neded */
|
|
||||||
int flip_map_len;
|
|
||||||
int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
|
|
||||||
defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true);
|
|
||||||
MEM_freeN(flip_map);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* single vgroup */
|
|
||||||
MDeformWeight *dw = defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
|
|
||||||
if (dw) {
|
|
||||||
dw->weight = defvert_find_weight(dvert_src, def_nr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ED_mesh_defvert_mirror_update_em(Object *ob, BMVert *eve, int def_nr, int vidx,
|
|
||||||
const int cd_dvert_offset)
|
|
||||||
{
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
BMEditMesh *em = me->edit_btmesh;
|
|
||||||
BMVert *eve_mirr;
|
|
||||||
|
|
||||||
eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx);
|
|
||||||
|
|
||||||
if (eve_mirr && eve_mirr != eve) {
|
|
||||||
MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
|
||||||
MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
|
|
||||||
mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
|
|
||||||
{
|
|
||||||
int vidx_mirr;
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
if (vidx == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
vidx_mirr = mesh_get_x_mirror_vert(ob, vidx);
|
|
||||||
|
|
||||||
if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
|
|
||||||
MDeformVert *dvert_src = &me->dvert[vidx];
|
|
||||||
MDeformVert *dvert_dst = &me->dvert[vidx_mirr];
|
|
||||||
mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vgroup_adjust_active(Object *ob, int def_nr)
|
|
||||||
{
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
BMEditMesh *em = me->edit_btmesh;
|
|
||||||
MDeformVert *dvert_act;
|
|
||||||
|
|
||||||
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
||||||
if (em) {
|
|
||||||
BMVert *eve_act;
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
|
|
||||||
if (dvert_act) {
|
|
||||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
|
||||||
ED_mesh_defvert_mirror_update_em(ob, eve_act, def_nr, -1, cd_dvert_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int v_act;
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
|
|
||||||
if (dvert_act) {
|
|
||||||
ED_mesh_defvert_mirror_update_ob(ob, def_nr, v_act);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vgroup_remove_weight(Object *ob, const int def_nr)
|
|
||||||
{
|
|
||||||
MDeformVert *dvert_act;
|
|
||||||
MDeformWeight *dw;
|
|
||||||
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_only(ob);
|
|
||||||
|
|
||||||
dw = defvert_find_index(dvert_act, def_nr);
|
|
||||||
defvert_remove_group(dvert_act, dw);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vgroup_copy_active_to_sel(Object *ob)
|
|
||||||
{
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
BMEditMesh *em = me->edit_btmesh;
|
|
||||||
MDeformVert *dvert_act;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (em) {
|
|
||||||
BMIter iter;
|
|
||||||
BMVert *eve, *eve_act;
|
|
||||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
|
||||||
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
|
|
||||||
if (dvert_act == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
|
|
||||||
if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve != eve_act) {
|
|
||||||
MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
|
||||||
defvert_copy(dv, dvert_act);
|
|
||||||
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
||||||
ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
MDeformVert *dv;
|
|
||||||
int v_act;
|
|
||||||
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
|
|
||||||
if (dvert_act == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dv = me->dvert;
|
|
||||||
for (i = 0; i < me->totvert; i++, dv++) {
|
|
||||||
if ((me->mvert[i].flag & SELECT) && dv != dvert_act) {
|
|
||||||
defvert_copy(dv, dvert_act);
|
|
||||||
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
||||||
ED_mesh_defvert_mirror_update_ob(ob, -1, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
|
|
||||||
{
|
|
||||||
MDeformVert *dvert_act;
|
|
||||||
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
BMEditMesh *em = me->edit_btmesh;
|
|
||||||
float weight_act;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (em) {
|
|
||||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
|
||||||
BMIter iter;
|
|
||||||
BMVert *eve, *eve_act;
|
|
||||||
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
|
|
||||||
if (dvert_act == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
weight_act = defvert_find_weight(dvert_act, def_nr);
|
|
||||||
|
|
||||||
BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
|
|
||||||
if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && (eve != eve_act)) {
|
|
||||||
MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
|
|
||||||
MDeformWeight *dw = defvert_find_index(dv, def_nr);
|
|
||||||
if (dw) {
|
|
||||||
dw->weight = weight_act;
|
|
||||||
|
|
||||||
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
||||||
ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
||||||
ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
MDeformVert *dv;
|
|
||||||
int v_act;
|
|
||||||
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
|
|
||||||
if (dvert_act == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
weight_act = defvert_find_weight(dvert_act, def_nr);
|
|
||||||
|
|
||||||
dv = me->dvert;
|
|
||||||
for (i = 0; i < me->totvert; i++, dv++) {
|
|
||||||
if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) {
|
|
||||||
MDeformWeight *dw = defvert_find_index(dv, def_nr);
|
|
||||||
if (dw) {
|
|
||||||
dw->weight = weight_act;
|
|
||||||
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
||||||
ED_mesh_defvert_mirror_update_ob(ob, -1, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
||||||
ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vgroup_normalize_active(Object *ob)
|
|
||||||
{
|
|
||||||
Mesh *me = ob->data;
|
|
||||||
BMEditMesh *em = me->edit_btmesh;
|
|
||||||
BMVert *eve_act;
|
|
||||||
int v_act;
|
|
||||||
MDeformVert *dvert_act;
|
|
||||||
|
|
||||||
if (em) {
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dvert_act == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
defvert_normalize(dvert_act);
|
|
||||||
|
|
||||||
if (me->editflag & ME_EDIT_MIRROR_X) {
|
|
||||||
if (em) {
|
|
||||||
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
|
|
||||||
ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int v_act = BKE_mesh_mselect_active_get(me, ME_VSEL);
|
|
||||||
ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event)
|
static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event)
|
||||||
{
|
{
|
||||||
Scene *scene = CTX_data_scene(C);
|
if (event < B_VGRP_PNL_EDIT_SINGLE) {
|
||||||
Object *ob = scene->basact->object;
|
/* not for me */
|
||||||
|
return;
|
||||||
/* XXX TODO Use operators? */
|
|
||||||
if (event == B_VGRP_PNL_NORMALIZE) {
|
|
||||||
vgroup_normalize_active(ob);
|
|
||||||
}
|
|
||||||
else if (event == B_VGRP_PNL_COPY) {
|
|
||||||
vgroup_copy_active_to_sel(ob);
|
|
||||||
}
|
|
||||||
else if (event >= B_VGRP_PNL_ACTIVE) {
|
|
||||||
ob->actdef = event - B_VGRP_PNL_ACTIVE + 1;
|
|
||||||
}
|
|
||||||
else if (event >= B_VGRP_PNL_COPY_SINGLE) {
|
|
||||||
vgroup_copy_active_to_sel_single(ob, event - B_VGRP_PNL_COPY_SINGLE);
|
|
||||||
}
|
|
||||||
else if (event >= B_VGRP_PNL_DELETE_SINGLE) {
|
|
||||||
vgroup_remove_weight(ob, event - B_VGRP_PNL_DELETE_SINGLE);
|
|
||||||
}
|
|
||||||
else if (event >= B_VGRP_PNL_EDIT_SINGLE) {
|
|
||||||
vgroup_adjust_active(ob, event - B_VGRP_PNL_EDIT_SINGLE);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BLI_assert(0);
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
Object *ob = scene->basact->object;
|
||||||
|
ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE);
|
||||||
|
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* TODO */
|
|
||||||
if (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X)
|
|
||||||
ED_vgroup_mirror(ob, 1, 1, 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* default for now */
|
|
||||||
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
|
static int view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
|
||||||
@ -1132,22 +871,39 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
|
|||||||
dv = ED_mesh_active_dvert_get_only(ob);
|
dv = ED_mesh_active_dvert_get_only(ob);
|
||||||
|
|
||||||
if (dv && dv->totweight) {
|
if (dv && dv->totweight) {
|
||||||
uiLayout *col;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
|
|
||||||
|
wmOperatorType *ot_weight_set_active = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true);
|
||||||
|
wmOperatorType *ot_weight_paste = WM_operatortype_find("OBJECT_OT_vertex_weight_paste", true);
|
||||||
|
wmOperatorType *ot_weight_delete = WM_operatortype_find("OBJECT_OT_vertex_weight_delete", true);
|
||||||
|
|
||||||
|
wmOperatorType *ot;
|
||||||
|
PointerRNA op_ptr, tools_ptr;
|
||||||
|
PointerRNA *but_ptr;
|
||||||
|
|
||||||
|
uiLayout *col, *bcol;
|
||||||
uiLayout *row;
|
uiLayout *row;
|
||||||
uiLayout *box;
|
uiLayout *box;
|
||||||
uiBut *but;
|
uiBut *but;
|
||||||
bDeformGroup *dg;
|
bDeformGroup *dg;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int subset_count, vgroup_tot;
|
int subset_count, vgroup_tot;
|
||||||
bool *vgroup_validmap;
|
const bool *vgroup_validmap;
|
||||||
eVGroupSelect subset_type = WT_VGROUP_ALL;
|
eVGroupSelect subset_type = ts->vgroupsubset;
|
||||||
int yco = 0;
|
int yco = 0;
|
||||||
|
|
||||||
uiBlockSetHandleFunc(block, do_view3d_vgroup_buttons, NULL);
|
uiBlockSetHandleFunc(block, do_view3d_vgroup_buttons, NULL);
|
||||||
box = uiLayoutBox(pa->layout);
|
|
||||||
|
bcol = uiLayoutColumn(pa->layout, true);
|
||||||
|
row = uiLayoutRow(bcol, true); /* The filter button row */
|
||||||
|
|
||||||
|
RNA_pointer_create(NULL, &RNA_ToolSettings, ts, &tools_ptr);
|
||||||
|
uiItemR(row, &tools_ptr, "vertex_group_subset", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
col = uiLayoutColumn(bcol, true);
|
||||||
|
box = uiLayoutBox(col); /* The list box */
|
||||||
|
|
||||||
col = uiLayoutColumn(box, true);
|
col = uiLayoutColumn(box, true);
|
||||||
|
|
||||||
vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
|
||||||
for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) {
|
for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) {
|
||||||
if (vgroup_validmap[i]) {
|
if (vgroup_validmap[i]) {
|
||||||
@ -1155,56 +911,68 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
|
|||||||
if (dw) {
|
if (dw) {
|
||||||
int x, xco = 0;
|
int x, xco = 0;
|
||||||
row = uiLayoutRow(col, true);
|
row = uiLayoutRow(col, true);
|
||||||
(void)row;
|
|
||||||
|
|
||||||
uiBlockSetEmboss(block, UI_EMBOSSN);
|
uiBlockSetEmboss(block, UI_EMBOSSN);
|
||||||
but = uiDefBut(block, BUT, B_VGRP_PNL_ACTIVE + i, dg->name,
|
|
||||||
xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y,
|
|
||||||
NULL, 0.0, 1.0, 1, 3, "");
|
|
||||||
uiButSetFlag(but, UI_TEXT_LEFT);
|
|
||||||
|
|
||||||
|
/* The Weight Group Name */
|
||||||
|
|
||||||
|
ot = ot_weight_set_active;
|
||||||
|
but = uiDefButO_ptr(block, BUT, ot, WM_OP_EXEC_DEFAULT, dg->name,
|
||||||
|
xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, "");
|
||||||
|
but_ptr = uiButGetOperatorPtrRNA(but);
|
||||||
|
RNA_int_set(but_ptr, "weight_group", i);
|
||||||
|
uiButSetFlag(but, UI_TEXT_LEFT);
|
||||||
if (ob->actdef != i + 1) {
|
if (ob->actdef != i + 1) {
|
||||||
uiButSetFlag(but, UI_BUT_INACTIVE);
|
uiButSetFlag(but, UI_BUT_INACTIVE);
|
||||||
}
|
}
|
||||||
xco += x;
|
xco += x;
|
||||||
|
|
||||||
//uiBlockSetEmboss(block, UI_EMBOSS);
|
/* The weight group value */
|
||||||
|
/* To be reworked still */
|
||||||
but = uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + i, "",
|
but = uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + i, "",
|
||||||
xco, yco, (x = UI_UNIT_X * 4), UI_UNIT_Y,
|
xco, yco, (x = UI_UNIT_X * 4), UI_UNIT_Y,
|
||||||
&dw->weight, 0.0, 1.0, 1, 3, "");
|
&dw->weight, 0.0, 1.0, 1, 3, "");
|
||||||
uiButSetFlag(but, UI_TEXT_LEFT);
|
uiButSetFlag(but, UI_TEXT_LEFT);
|
||||||
xco += x;
|
xco += x;
|
||||||
|
|
||||||
uiDefIconBut(block, BUT, B_VGRP_PNL_COPY_SINGLE + i, ICON_PASTEDOWN,
|
/* The weight group paste function */
|
||||||
xco, yco, (x = UI_UNIT_X), UI_UNIT_Y,
|
|
||||||
NULL, 0, 0, 0, 0, TIP_("Copy this group's weight to other selected verts"));
|
|
||||||
xco += x;
|
|
||||||
|
|
||||||
uiDefIconBut(block, BUT, B_VGRP_PNL_DELETE_SINGLE + i, ICON_X,
|
ot = ot_weight_paste;
|
||||||
xco, yco, (x = UI_UNIT_X), UI_UNIT_Y,
|
WM_operator_properties_create_ptr(&op_ptr, ot);
|
||||||
NULL, 0, 0, 0, 0, TIP_("Delete this weight from the vertex"));
|
RNA_int_set(&op_ptr, "weight_group", i);
|
||||||
xco += x;
|
uiItemFullO_ptr(row, ot, "", ICON_PASTEDOWN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
|
||||||
|
|
||||||
|
/* The weight entry delete function */
|
||||||
|
|
||||||
|
ot = ot_weight_delete;
|
||||||
|
WM_operator_properties_create_ptr(&op_ptr, ot);
|
||||||
|
RNA_int_set(&op_ptr, "weight_group", i);
|
||||||
|
uiItemFullO_ptr(row, ot, "", ICON_X, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
|
||||||
|
|
||||||
yco -= UI_UNIT_Y;
|
yco -= UI_UNIT_Y;
|
||||||
(void)xco;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MEM_freeN(vgroup_validmap);
|
MEM_freeN((void *)vgroup_validmap);
|
||||||
|
|
||||||
|
uiBlockSetEmboss(block, UI_EMBOSS);
|
||||||
|
|
||||||
yco -= 2;
|
yco -= 2;
|
||||||
|
|
||||||
uiBlockSetEmboss(block, UI_EMBOSS);
|
|
||||||
col = uiLayoutColumn(pa->layout, true);
|
col = uiLayoutColumn(pa->layout, true);
|
||||||
row = uiLayoutRow(col, true);
|
row = uiLayoutRow(col, true);
|
||||||
|
|
||||||
uiDefBut(block, BUT, B_VGRP_PNL_NORMALIZE, IFACE_("Normalize"),
|
ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active", 1);
|
||||||
0, yco, UI_UNIT_X * 5, UI_UNIT_Y,
|
but = uiDefButO_ptr(block, BUT, ot, WM_OP_EXEC_DEFAULT, "Normalize",
|
||||||
NULL, 0, 0, 0, 0, TIP_("Normalize active vertex weights"));
|
0, yco,UI_UNIT_X * 5, UI_UNIT_Y,
|
||||||
uiDefBut(block, BUT, B_VGRP_PNL_COPY, IFACE_("Copy"),
|
TIP_("Normalize active vertex weights"));
|
||||||
UI_UNIT_X * 5, yco, UI_UNIT_X * 5, UI_UNIT_Y,
|
|
||||||
NULL, 0, 0, 0, 0, TIP_("Copy active vertex to other selected verts"));
|
ot = WM_operatortype_find("OBJECT_OT_vertex_weight_copy", 1);
|
||||||
|
but = uiDefButO_ptr(block, BUT, ot, WM_OP_EXEC_DEFAULT, "Copy",
|
||||||
|
UI_UNIT_X * 5, yco,UI_UNIT_X * 5, UI_UNIT_Y,
|
||||||
|
TIP_("Copy active vertex to other selected verts"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,11 +1076,11 @@ typedef struct ToolSettings {
|
|||||||
short proportional, prop_mode;
|
short proportional, prop_mode;
|
||||||
char proportional_objects; /* proportional edit, object mode */
|
char proportional_objects; /* proportional edit, object mode */
|
||||||
char proportional_mask; /* proportional edit, object mode */
|
char proportional_mask; /* proportional edit, object mode */
|
||||||
char pad4[1];
|
|
||||||
|
|
||||||
char auto_normalize; /*auto normalizing mode in wpaint*/
|
char auto_normalize; /*auto normalizing mode in wpaint*/
|
||||||
char multipaint; /* paint multiple bones in wpaint */
|
char multipaint; /* paint multiple bones in wpaint */
|
||||||
char weightuser;
|
char weightuser;
|
||||||
|
char vgroupsubset; /* subset selection filter in wpaint */
|
||||||
|
|
||||||
/* UV painting */
|
/* UV painting */
|
||||||
int use_uv_sculpt;
|
int use_uv_sculpt;
|
||||||
@ -1511,6 +1511,24 @@ enum {
|
|||||||
OB_DRAW_GROUPUSER_ALL = 2
|
OB_DRAW_GROUPUSER_ALL = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* toolsettings->vgroupsubset */
|
||||||
|
/* object_vgroup.c */
|
||||||
|
typedef enum eVGroupSelect {
|
||||||
|
WT_VGROUP_ALL = 0,
|
||||||
|
WT_VGROUP_ACTIVE = 1,
|
||||||
|
WT_VGROUP_BONE_SELECT = 2,
|
||||||
|
WT_VGROUP_BONE_DEFORM = 3,
|
||||||
|
WT_VGROUP_BONE_DEFORM_OFF = 4
|
||||||
|
} eVGroupSelect;
|
||||||
|
|
||||||
|
#define WT_VGROUP_MASK_ALL \
|
||||||
|
((1 << WT_VGROUP_ACTIVE) | \
|
||||||
|
(1 << WT_VGROUP_BONE_SELECT) | \
|
||||||
|
(1 << WT_VGROUP_BONE_DEFORM) | \
|
||||||
|
(1 << WT_VGROUP_BONE_DEFORM_OFF) | \
|
||||||
|
(1 << WT_VGROUP_ALL))
|
||||||
|
|
||||||
|
|
||||||
/* sce->flag */
|
/* sce->flag */
|
||||||
#define SCE_DS_SELECTED (1<<0)
|
#define SCE_DS_SELECTED (1<<0)
|
||||||
#define SCE_DS_COLLAPSED (1<<1)
|
#define SCE_DS_COLLAPSED (1<<1)
|
||||||
|
@ -1640,6 +1640,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static EnumPropertyItem vertex_group_select_items[] = {
|
||||||
|
{WT_VGROUP_ALL, "ALL", 0, "All", "All Vertex Groups"},
|
||||||
|
{WT_VGROUP_BONE_DEFORM, "BONE_DEFORM", 0, "Deform", "Vertex Groups assigned to Deform Bones"},
|
||||||
|
{WT_VGROUP_BONE_DEFORM_OFF, "OTHER_DEFORM", 0, "Other", "Vertex Groups assigned to non Deform Bones"},
|
||||||
|
{0, NULL, 0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
srna = RNA_def_struct(brna, "ToolSettings", NULL);
|
srna = RNA_def_struct(brna, "ToolSettings", NULL);
|
||||||
RNA_def_struct_path_func(srna, "rna_ToolSettings_path");
|
RNA_def_struct_path_func(srna, "rna_ToolSettings_path");
|
||||||
RNA_def_struct_ui_text(srna, "Tool Settings", "");
|
RNA_def_struct_ui_text(srna, "Tool Settings", "");
|
||||||
@ -1668,10 +1676,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "Mask Non-Group Vertices", "Display unweighted vertices (multi-paint overrides)");
|
RNA_def_property_ui_text(prop, "Mask Non-Group Vertices", "Display unweighted vertices (multi-paint overrides)");
|
||||||
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
|
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "vertex_group_subset", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, NULL, "vgroupsubset");
|
||||||
|
RNA_def_property_enum_items(prop, vertex_group_select_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Subset", "Filter Vertex groups for Display");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "vertex_paint", PROP_POINTER, PROP_NONE);
|
prop = RNA_def_property(srna, "vertex_paint", PROP_POINTER, PROP_NONE);
|
||||||
RNA_def_property_pointer_sdna(prop, NULL, "vpaint");
|
RNA_def_property_pointer_sdna(prop, NULL, "vpaint"); RNA_def_property_ui_text(prop, "Vertex Paint", "");
|
||||||
RNA_def_property_ui_text(prop, "Vertex Paint", "");
|
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "weight_paint", PROP_POINTER, PROP_NONE);
|
prop = RNA_def_property(srna, "weight_paint", PROP_POINTER, PROP_NONE);
|
||||||
RNA_def_property_pointer_sdna(prop, NULL, "wpaint");
|
RNA_def_property_pointer_sdna(prop, NULL, "wpaint");
|
||||||
|
Loading…
Reference in New Issue
Block a user