forked from bartvdbraak/blender
- particle drawing was using invalid memory with weights.
- particle set weight operator (Shift + K) and from the menu. - mirror vertex groups operator can also flip weight group names. a number of utility functions for weight groups added int *get_defgroup_flip_map(struct Object *ob); void flip_vertexgroup_name (char *name_r, const char *name, int strip_number); // moved from modifier.c void copy_defvert (struct MDeformVert *dvert_r, const struct MDeformVert *dvert); void flip_defvert (struct MDeformVert *dvert, int *flip_map);
This commit is contained in:
parent
a4732eefa5
commit
ace8d45c1c
@ -186,6 +186,8 @@ class VIEW3D_MT_mirror(bpy.types.Menu):
|
|||||||
props.constraint_axis = (False, False, True)
|
props.constraint_axis = (False, False, True)
|
||||||
props.constraint_orientation = 'LOCAL'
|
props.constraint_orientation = 'LOCAL'
|
||||||
|
|
||||||
|
layout.operator("object.vertex_group_mirror")
|
||||||
|
|
||||||
|
|
||||||
class VIEW3D_MT_snap(bpy.types.Menu):
|
class VIEW3D_MT_snap(bpy.types.Menu):
|
||||||
bl_label = "Snap"
|
bl_label = "Snap"
|
||||||
@ -898,6 +900,7 @@ class VIEW3D_MT_particle(bpy.types.Menu):
|
|||||||
layout.operator("particle.subdivide")
|
layout.operator("particle.subdivide")
|
||||||
|
|
||||||
layout.operator("particle.rekey")
|
layout.operator("particle.rekey")
|
||||||
|
layout.operator("particle.weight_set")
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
|
@ -44,11 +44,16 @@ void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2);
|
|||||||
struct bDeformGroup *copy_defgroup (struct bDeformGroup *ingroup);
|
struct bDeformGroup *copy_defgroup (struct bDeformGroup *ingroup);
|
||||||
struct bDeformGroup *get_named_vertexgroup (Object *ob, char *name);
|
struct bDeformGroup *get_named_vertexgroup (Object *ob, char *name);
|
||||||
int get_defgroup_num (struct Object *ob, struct bDeformGroup *dg);
|
int get_defgroup_num (struct Object *ob, struct bDeformGroup *dg);
|
||||||
|
int *get_defgroup_flip_map(struct Object *ob);
|
||||||
int get_named_vertexgroup_num (Object *ob, const char *name);
|
int get_named_vertexgroup_num (Object *ob, const char *name);
|
||||||
void unique_vertexgroup_name (struct bDeformGroup *dg, struct Object *ob);
|
void unique_vertexgroup_name (struct bDeformGroup *dg, struct Object *ob);
|
||||||
|
void flip_vertexgroup_name (char *name_r, const char *name, int strip_number);
|
||||||
|
|
||||||
float deformvert_get_weight(const struct MDeformVert *dvert, int group_num);
|
float deformvert_get_weight(const struct MDeformVert *dvert, int group_num);
|
||||||
float vertexgroup_get_vertex_weight(const struct MDeformVert *dvert, int index, int group_num);
|
float vertexgroup_get_vertex_weight(const struct MDeformVert *dvert, int index, int group_num);
|
||||||
|
|
||||||
|
void copy_defvert (struct MDeformVert *dvert_r, const struct MDeformVert *dvert);
|
||||||
|
void flip_defvert (struct MDeformVert *dvert, int *flip_map);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "ctype.h"
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
@ -95,6 +96,36 @@ bDeformGroup *copy_defgroup (bDeformGroup *ingroup)
|
|||||||
return outgroup;
|
return outgroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copy_defvert (MDeformVert *dvert_r, const MDeformVert *dvert)
|
||||||
|
{
|
||||||
|
if(dvert_r->totweight == dvert->totweight) {
|
||||||
|
if(dvert->totweight)
|
||||||
|
memcpy(dvert_r->dw, dvert->dw, dvert->totweight * sizeof(MDeformWeight));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(dvert_r->dw)
|
||||||
|
MEM_freeN(dvert_r->dw);
|
||||||
|
|
||||||
|
if(dvert->totweight)
|
||||||
|
dvert_r->dw= MEM_dupallocN(dvert->dw);
|
||||||
|
else
|
||||||
|
dvert_r->dw= NULL;
|
||||||
|
|
||||||
|
dvert_r->totweight = dvert->totweight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flip_defvert (MDeformVert *dvert, int *flip_map)
|
||||||
|
{
|
||||||
|
MDeformWeight *dw;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(dw= dvert->dw, i=0; i<dvert->totweight; dw++, i++)
|
||||||
|
if(flip_map[dw->def_nr] >= 0)
|
||||||
|
dw->def_nr= flip_map[dw->def_nr];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bDeformGroup *get_named_vertexgroup (Object *ob, char *name)
|
bDeformGroup *get_named_vertexgroup (Object *ob, char *name)
|
||||||
{
|
{
|
||||||
/* return a pointer to the deform group with this name
|
/* return a pointer to the deform group with this name
|
||||||
@ -167,6 +198,36 @@ int get_defgroup_num (Object *ob, bDeformGroup *dg)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* note, must be freed */
|
||||||
|
int *get_defgroup_flip_map(Object *ob)
|
||||||
|
{
|
||||||
|
bDeformGroup *dg;
|
||||||
|
int totdg= BLI_countlist(&ob->defbase);
|
||||||
|
|
||||||
|
if(totdg==0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char name[sizeof(dg->name)];
|
||||||
|
int i, flip_num, *map= MEM_mallocN(totdg * sizeof(int), "get_defgroup_flip_map");
|
||||||
|
memset(map, -1, totdg * sizeof(int));
|
||||||
|
|
||||||
|
for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
|
||||||
|
if(map[i] == -1) { /* may be calculated previously */
|
||||||
|
flip_vertexgroup_name(name, dg->name, 0);
|
||||||
|
if(strcmp(name, dg->name)) {
|
||||||
|
flip_num= get_named_vertexgroup_num(ob, name);
|
||||||
|
if(flip_num > -1) {
|
||||||
|
map[i]= flip_num;
|
||||||
|
map[flip_num]= i; /* save an extra lookup */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void unique_vertexgroup_name (bDeformGroup *dg, Object *ob)
|
void unique_vertexgroup_name (bDeformGroup *dg, Object *ob)
|
||||||
{
|
{
|
||||||
bDeformGroup *curdef;
|
bDeformGroup *curdef;
|
||||||
@ -221,6 +282,121 @@ void unique_vertexgroup_name (bDeformGroup *dg, Object *ob)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* finds the best possible flipped name. For renaming; check for unique names afterwards */
|
||||||
|
/* if strip_number: removes number extensions */
|
||||||
|
void flip_vertexgroup_name (char *name_r, const char *name, int strip_number)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char prefix[sizeof((bDeformGroup *)NULL)->name]={""}; /* The part before the facing */
|
||||||
|
char suffix[sizeof((bDeformGroup *)NULL)->name]={""}; /* The part after the facing */
|
||||||
|
char replace[sizeof((bDeformGroup *)NULL)->name]={""}; /* The replacement string */
|
||||||
|
char number[sizeof((bDeformGroup *)NULL)->name]={""}; /* The number extension string */
|
||||||
|
char *index=NULL;
|
||||||
|
|
||||||
|
len= strlen(name);
|
||||||
|
if(len<3) return; // we don't do names like .R or .L
|
||||||
|
|
||||||
|
/* We first check the case with a .### extension, let's find the last period */
|
||||||
|
if(isdigit(name[len-1])) {
|
||||||
|
index= strrchr(name, '.'); // last occurrence
|
||||||
|
if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
|
||||||
|
if(strip_number==0)
|
||||||
|
strcpy(number, index);
|
||||||
|
*index= 0;
|
||||||
|
len= strlen(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy (prefix, name);
|
||||||
|
|
||||||
|
#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
|
||||||
|
|
||||||
|
/* first case; separator . - _ with extensions r R l L */
|
||||||
|
if( IS_SEPARATOR(name[len-2]) ) {
|
||||||
|
switch(name[len-1]) {
|
||||||
|
case 'l':
|
||||||
|
prefix[len-1]= 0;
|
||||||
|
strcpy(replace, "r");
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
prefix[len-1]= 0;
|
||||||
|
strcpy(replace, "l");
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
prefix[len-1]= 0;
|
||||||
|
strcpy(replace, "R");
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
prefix[len-1]= 0;
|
||||||
|
strcpy(replace, "L");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* case; beginning with r R l L , with separator after it */
|
||||||
|
else if( IS_SEPARATOR(name[1]) ) {
|
||||||
|
switch(name[0]) {
|
||||||
|
case 'l':
|
||||||
|
strcpy(replace, "r");
|
||||||
|
strcpy(suffix, name+1);
|
||||||
|
prefix[0]= 0;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
strcpy(replace, "l");
|
||||||
|
strcpy(suffix, name+1);
|
||||||
|
prefix[0]= 0;
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
strcpy(replace, "R");
|
||||||
|
strcpy(suffix, name+1);
|
||||||
|
prefix[0]= 0;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
strcpy(replace, "L");
|
||||||
|
strcpy(suffix, name+1);
|
||||||
|
prefix[0]= 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(len > 5) {
|
||||||
|
/* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
|
||||||
|
index = BLI_strcasestr(prefix, "right");
|
||||||
|
if (index==prefix || index==prefix+len-5) {
|
||||||
|
if(index[0]=='r')
|
||||||
|
strcpy (replace, "left");
|
||||||
|
else {
|
||||||
|
if(index[1]=='I')
|
||||||
|
strcpy (replace, "LEFT");
|
||||||
|
else
|
||||||
|
strcpy (replace, "Left");
|
||||||
|
}
|
||||||
|
*index= 0;
|
||||||
|
strcpy (suffix, index+5);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
index = BLI_strcasestr(prefix, "left");
|
||||||
|
if (index==prefix || index==prefix+len-4) {
|
||||||
|
if(index[0]=='l')
|
||||||
|
strcpy (replace, "right");
|
||||||
|
else {
|
||||||
|
if(index[1]=='E')
|
||||||
|
strcpy (replace, "RIGHT");
|
||||||
|
else
|
||||||
|
strcpy (replace, "Right");
|
||||||
|
}
|
||||||
|
*index= 0;
|
||||||
|
strcpy (suffix, index+4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef IS_SEPARATOR
|
||||||
|
|
||||||
|
sprintf (name_r, "%s%s%s%s", prefix, replace, suffix, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
float deformvert_get_weight(const struct MDeformVert *dvert, int group_num)
|
float deformvert_get_weight(const struct MDeformVert *dvert, int group_num)
|
||||||
{
|
{
|
||||||
if(dvert)
|
if(dvert)
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "float.h"
|
#include "float.h"
|
||||||
#include "ctype.h"
|
|
||||||
|
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
@ -1801,118 +1800,6 @@ static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finds the best possible flipped name. For renaming; check for unique names afterwards */
|
|
||||||
/* if strip_number: removes number extensions */
|
|
||||||
static void vertgroup_flip_name (char *name, int strip_number)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
char prefix[128]={""}; /* The part before the facing */
|
|
||||||
char suffix[128]={""}; /* The part after the facing */
|
|
||||||
char replace[128]={""}; /* The replacement string */
|
|
||||||
char number[128]={""}; /* The number extension string */
|
|
||||||
char *index=NULL;
|
|
||||||
|
|
||||||
len= strlen(name);
|
|
||||||
if(len<3) return; // we don't do names like .R or .L
|
|
||||||
|
|
||||||
/* We first check the case with a .### extension, let's find the last period */
|
|
||||||
if(isdigit(name[len-1])) {
|
|
||||||
index= strrchr(name, '.'); // last occurrence
|
|
||||||
if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
|
|
||||||
if(strip_number==0)
|
|
||||||
strcpy(number, index);
|
|
||||||
*index= 0;
|
|
||||||
len= strlen(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy (prefix, name);
|
|
||||||
|
|
||||||
#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
|
|
||||||
|
|
||||||
/* first case; separator . - _ with extensions r R l L */
|
|
||||||
if( IS_SEPARATOR(name[len-2]) ) {
|
|
||||||
switch(name[len-1]) {
|
|
||||||
case 'l':
|
|
||||||
prefix[len-1]= 0;
|
|
||||||
strcpy(replace, "r");
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
prefix[len-1]= 0;
|
|
||||||
strcpy(replace, "l");
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
prefix[len-1]= 0;
|
|
||||||
strcpy(replace, "R");
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
prefix[len-1]= 0;
|
|
||||||
strcpy(replace, "L");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* case; beginning with r R l L , with separator after it */
|
|
||||||
else if( IS_SEPARATOR(name[1]) ) {
|
|
||||||
switch(name[0]) {
|
|
||||||
case 'l':
|
|
||||||
strcpy(replace, "r");
|
|
||||||
strcpy(suffix, name+1);
|
|
||||||
prefix[0]= 0;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
strcpy(replace, "l");
|
|
||||||
strcpy(suffix, name+1);
|
|
||||||
prefix[0]= 0;
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
strcpy(replace, "R");
|
|
||||||
strcpy(suffix, name+1);
|
|
||||||
prefix[0]= 0;
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
strcpy(replace, "L");
|
|
||||||
strcpy(suffix, name+1);
|
|
||||||
prefix[0]= 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(len > 5) {
|
|
||||||
/* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
|
|
||||||
index = BLI_strcasestr(prefix, "right");
|
|
||||||
if (index==prefix || index==prefix+len-5) {
|
|
||||||
if(index[0]=='r')
|
|
||||||
strcpy (replace, "left");
|
|
||||||
else {
|
|
||||||
if(index[1]=='I')
|
|
||||||
strcpy (replace, "LEFT");
|
|
||||||
else
|
|
||||||
strcpy (replace, "Left");
|
|
||||||
}
|
|
||||||
*index= 0;
|
|
||||||
strcpy (suffix, index+5);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
index = BLI_strcasestr(prefix, "left");
|
|
||||||
if (index==prefix || index==prefix+len-4) {
|
|
||||||
if(index[0]=='l')
|
|
||||||
strcpy (replace, "right");
|
|
||||||
else {
|
|
||||||
if(index[1]=='E')
|
|
||||||
strcpy (replace, "RIGHT");
|
|
||||||
else
|
|
||||||
strcpy (replace, "Right");
|
|
||||||
}
|
|
||||||
*index= 0;
|
|
||||||
strcpy (suffix, index+4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef IS_SEPARATOR
|
|
||||||
|
|
||||||
sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|
static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|
||||||
Object *ob,
|
Object *ob,
|
||||||
DerivedMesh *dm,
|
DerivedMesh *dm,
|
||||||
@ -2022,8 +1909,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
def = vector_def[dvert->dw[j].def_nr];
|
def = vector_def[dvert->dw[j].def_nr];
|
||||||
strcpy(tmpname, def->name);
|
flip_vertexgroup_name(tmpname, def->name, 0);
|
||||||
vertgroup_flip_name(tmpname,0);
|
|
||||||
|
|
||||||
for(b = 0, defb = ob->defbase.first; defb;
|
for(b = 0, defb = ob->defbase.first; defb;
|
||||||
defb = defb->next, b++)
|
defb = defb->next, b++)
|
||||||
|
@ -2999,8 +2999,8 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
|
|||||||
|
|
||||||
/* should init_particle_interpolation set this ? */
|
/* should init_particle_interpolation set this ? */
|
||||||
if(pset->brushtype==PE_BRUSH_WEIGHT){
|
if(pset->brushtype==PE_BRUSH_WEIGHT){
|
||||||
pind.hkey[0] = pa->hair;
|
pind.hkey[0] = NULL;
|
||||||
pind.hkey[1] = pa->hair + 1;
|
pind.hkey[1] = pa->hair;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3036,12 +3036,6 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
|
|||||||
|
|
||||||
do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
|
do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
|
||||||
|
|
||||||
/* should init_particle_interpolation set this ? */
|
|
||||||
if(pset->brushtype==PE_BRUSH_WEIGHT){
|
|
||||||
pind.hkey[0] = pind.hkey[1];
|
|
||||||
pind.hkey[1]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* non-hair points are already in global space */
|
/* non-hair points are already in global space */
|
||||||
if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
|
if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
|
||||||
mul_m4_v3(hairmat, result.co);
|
mul_m4_v3(hairmat, result.co);
|
||||||
@ -3099,10 +3093,17 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
|
|||||||
|
|
||||||
/* selection coloring in edit mode */
|
/* selection coloring in edit mode */
|
||||||
if(pset->brushtype==PE_BRUSH_WEIGHT){
|
if(pset->brushtype==PE_BRUSH_WEIGHT){
|
||||||
if(k==steps)
|
if(k==0)
|
||||||
|
weight_to_rgb(pind.hkey[1]->weight, ca->col, ca->col+1, ca->col+2);
|
||||||
|
else if(k >= steps - 1)
|
||||||
weight_to_rgb(pind.hkey[0]->weight, ca->col, ca->col+1, ca->col+2);
|
weight_to_rgb(pind.hkey[0]->weight, ca->col, ca->col+1, ca->col+2);
|
||||||
else
|
else
|
||||||
weight_to_rgb((1.0f - keytime) * pind.hkey[0]->weight + keytime * pind.hkey[1]->weight, ca->col, ca->col+1, ca->col+2);
|
weight_to_rgb((1.0f - keytime) * pind.hkey[0]->weight + keytime * pind.hkey[1]->weight, ca->col, ca->col+1, ca->col+2);
|
||||||
|
|
||||||
|
/* at the moment this is only used for weight painting.
|
||||||
|
* will need to move out of this check if its used elsewhere. */
|
||||||
|
pind.hkey[0] = pind.hkey[1];
|
||||||
|
pind.hkey[1]++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT){
|
if((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT){
|
||||||
|
@ -120,7 +120,7 @@ void EM_cache_x_mirror_vert(struct Object *ob, struct EditMesh *em)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EM_select_mirrored(Object *obedit, EditMesh *em, int extend)
|
static void EM_select_mirrored(Object *obedit, EditMesh *em, int extend)
|
||||||
{
|
{
|
||||||
|
|
||||||
EditVert *eve;
|
EditVert *eve;
|
||||||
|
@ -187,6 +187,7 @@ void OBJECT_OT_vertex_group_levels(struct wmOperatorType *ot);
|
|||||||
void OBJECT_OT_vertex_group_invert(struct wmOperatorType *ot);
|
void OBJECT_OT_vertex_group_invert(struct wmOperatorType *ot);
|
||||||
void OBJECT_OT_vertex_group_blend(struct wmOperatorType *ot);
|
void OBJECT_OT_vertex_group_blend(struct wmOperatorType *ot);
|
||||||
void OBJECT_OT_vertex_group_clean(struct wmOperatorType *ot);
|
void OBJECT_OT_vertex_group_clean(struct wmOperatorType *ot);
|
||||||
|
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_game_property_new(struct wmOperatorType *ot);
|
void OBJECT_OT_game_property_new(struct wmOperatorType *ot);
|
||||||
|
@ -173,6 +173,7 @@ void ED_operatortypes_object(void)
|
|||||||
WM_operatortype_append(OBJECT_OT_vertex_group_levels);
|
WM_operatortype_append(OBJECT_OT_vertex_group_levels);
|
||||||
WM_operatortype_append(OBJECT_OT_vertex_group_blend);
|
WM_operatortype_append(OBJECT_OT_vertex_group_blend);
|
||||||
WM_operatortype_append(OBJECT_OT_vertex_group_clean);
|
WM_operatortype_append(OBJECT_OT_vertex_group_clean);
|
||||||
|
WM_operatortype_append(OBJECT_OT_vertex_group_mirror);
|
||||||
WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
|
WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
|
||||||
|
|
||||||
WM_operatortype_append(OBJECT_OT_game_property_new);
|
WM_operatortype_append(OBJECT_OT_game_property_new);
|
||||||
|
@ -903,6 +903,68 @@ static void vgroup_clean_all(Object *ob, float eul, int keep_single)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vgroup_mirror(Object *ob, int mirror_weights, int flip_vgroups)
|
||||||
|
{
|
||||||
|
EditVert *eve, *eve_mirr;
|
||||||
|
MDeformVert *dvert, *dvert_mirr;
|
||||||
|
int *flip_map;
|
||||||
|
|
||||||
|
if(mirror_weights==0 && flip_vgroups==0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* only the active group */
|
||||||
|
if(ob->type == OB_MESH) {
|
||||||
|
Mesh *me= ob->data;
|
||||||
|
EditMesh *em = BKE_mesh_get_editmesh(me);
|
||||||
|
|
||||||
|
EM_cache_x_mirror_vert(ob, em);
|
||||||
|
|
||||||
|
if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
|
||||||
|
return;
|
||||||
|
|
||||||
|
flip_map= get_defgroup_flip_map(ob);
|
||||||
|
|
||||||
|
/* Go through the list of editverts and assign them */
|
||||||
|
for(eve=em->verts.first; eve; eve=eve->next){
|
||||||
|
if((eve_mirr=eve->tmp.v)) {
|
||||||
|
if(eve_mirr->f & SELECT || eve->f & SELECT) {
|
||||||
|
dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
|
||||||
|
dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
|
||||||
|
if(dvert && dvert_mirr) {
|
||||||
|
if(eve_mirr->f & SELECT && eve->f & SELECT) {
|
||||||
|
/* swap */
|
||||||
|
if(mirror_weights)
|
||||||
|
SWAP(MDeformVert, *dvert, *dvert_mirr);
|
||||||
|
if(flip_vgroups) {
|
||||||
|
flip_defvert(dvert, flip_map);
|
||||||
|
flip_defvert(dvert_mirr, flip_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* dvert should always be the target */
|
||||||
|
if(eve_mirr->f & SELECT) {
|
||||||
|
SWAP(MDeformVert *, dvert, dvert_mirr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mirror_weights)
|
||||||
|
copy_defvert(dvert, dvert_mirr);
|
||||||
|
if(flip_vgroups) {
|
||||||
|
flip_defvert(dvert, flip_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eve->tmp.v= eve_mirr->tmp.v= NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_freeN(flip_map);
|
||||||
|
|
||||||
|
BKE_mesh_end_editmesh(me, em);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void vgroup_delete_update_users(Object *ob, int id)
|
static void vgroup_delete_update_users(Object *ob, int id)
|
||||||
{
|
{
|
||||||
ExplodeModifierData *emd;
|
ExplodeModifierData *emd;
|
||||||
@ -1026,7 +1088,7 @@ static void vgroup_active_remove_verts(Object *ob, int allverts)
|
|||||||
for(eve=em->verts.first; eve; eve=eve->next){
|
for(eve=em->verts.first; eve; eve=eve->next){
|
||||||
dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
|
dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
|
||||||
|
|
||||||
if(dvert && dvert->dw && ((eve->f & 1) || allverts)){
|
if(dvert && dvert->dw && ((eve->f & SELECT) || allverts)){
|
||||||
for(i=0; i<dvert->totweight; i++){
|
for(i=0; i<dvert->totweight; i++){
|
||||||
/* Find group */
|
/* Find group */
|
||||||
eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
|
eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
|
||||||
@ -1208,7 +1270,7 @@ static void vgroup_assign_verts(Object *ob, float weight)
|
|||||||
for(eve=em->verts.first; eve; eve=eve->next){
|
for(eve=em->verts.first; eve; eve=eve->next){
|
||||||
dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
|
dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
|
||||||
|
|
||||||
if(dvert && (eve->f & 1)){
|
if(dvert && (eve->f & SELECT)){
|
||||||
done=0;
|
done=0;
|
||||||
/* See if this vert already has a reference to this group */
|
/* See if this vert already has a reference to this group */
|
||||||
/* If so: Change its weight */
|
/* If so: Change its weight */
|
||||||
@ -1684,6 +1746,40 @@ void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
|
||||||
|
|
||||||
|
vgroup_mirror(ob, RNA_boolean_get(op->ptr,"mirror_weights"), RNA_boolean_get(op->ptr,"flip_group_names"));
|
||||||
|
|
||||||
|
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
/* identifiers */
|
||||||
|
ot->name= "Mirror Vertex Group";
|
||||||
|
ot->idname= "OBJECT_OT_vertex_group_mirror";
|
||||||
|
ot->description= "Mirror weights, and flip vertex group names, copying when only one side is selected.";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->poll= vertex_group_poll_edit;
|
||||||
|
ot->exec= vertex_group_mirror_exec;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights.");
|
||||||
|
RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names while mirroring.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op)
|
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Scene *scene= CTX_data_scene(C);
|
Scene *scene= CTX_data_scene(C);
|
||||||
|
@ -2366,6 +2366,52 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
|
|||||||
RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, "Threshold", "Threshold distance withing which particles are removed", 0.00001f, 0.1f);
|
RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, "Threshold", "Threshold distance withing which particles are removed", 0.00001f, 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int weight_set_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
Scene *scene= CTX_data_scene(C);
|
||||||
|
ParticleEditSettings *pset= PE_settings(scene);
|
||||||
|
Object *ob= CTX_data_active_object(C);
|
||||||
|
PTCacheEdit *edit= PE_get_current(scene, ob);
|
||||||
|
ParticleSystem *psys = edit->psys;
|
||||||
|
POINT_P;
|
||||||
|
KEY_K;
|
||||||
|
HairKey *hkey;
|
||||||
|
float weight;
|
||||||
|
ParticleBrushData *brush= &pset->brush[pset->brushtype];
|
||||||
|
edit= psys->edit;
|
||||||
|
|
||||||
|
weight= (float)(brush->strength / 100.0f);
|
||||||
|
|
||||||
|
LOOP_SELECTED_POINTS {
|
||||||
|
ParticleData *pa= psys->particles + p;
|
||||||
|
|
||||||
|
LOOP_SELECTED_KEYS {
|
||||||
|
hkey= pa->hair + k;
|
||||||
|
hkey->weight= weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
|
||||||
|
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, ob);
|
||||||
|
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PARTICLE_OT_weight_set(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
/* identifiers */
|
||||||
|
ot->name= "Weight Set";
|
||||||
|
ot->idname= "PARTICLE_OT_weight_set";
|
||||||
|
|
||||||
|
/* api callbacks */
|
||||||
|
ot->exec= weight_set_exec;
|
||||||
|
ot->poll= PE_poll;
|
||||||
|
|
||||||
|
/* flags */
|
||||||
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||||
|
}
|
||||||
|
|
||||||
/************************ cursor drawing *******************************/
|
/************************ cursor drawing *******************************/
|
||||||
|
|
||||||
static void brush_drawcursor(bContext *C, int x, int y, void *customdata)
|
static void brush_drawcursor(bContext *C, int x, int y, void *customdata)
|
||||||
|
@ -50,6 +50,7 @@ void PARTICLE_OT_reveal(struct wmOperatorType *ot);
|
|||||||
void PARTICLE_OT_rekey(struct wmOperatorType *ot);
|
void PARTICLE_OT_rekey(struct wmOperatorType *ot);
|
||||||
void PARTICLE_OT_subdivide(struct wmOperatorType *ot);
|
void PARTICLE_OT_subdivide(struct wmOperatorType *ot);
|
||||||
void PARTICLE_OT_remove_doubles(struct wmOperatorType *ot);
|
void PARTICLE_OT_remove_doubles(struct wmOperatorType *ot);
|
||||||
|
void PARTICLE_OT_weight_set(struct wmOperatorType *ot);
|
||||||
void PARTICLE_OT_delete(struct wmOperatorType *ot);
|
void PARTICLE_OT_delete(struct wmOperatorType *ot);
|
||||||
void PARTICLE_OT_mirror(struct wmOperatorType *ot);
|
void PARTICLE_OT_mirror(struct wmOperatorType *ot);
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ static void operatortypes_particle(void)
|
|||||||
WM_operatortype_append(PARTICLE_OT_rekey);
|
WM_operatortype_append(PARTICLE_OT_rekey);
|
||||||
WM_operatortype_append(PARTICLE_OT_subdivide);
|
WM_operatortype_append(PARTICLE_OT_subdivide);
|
||||||
WM_operatortype_append(PARTICLE_OT_remove_doubles);
|
WM_operatortype_append(PARTICLE_OT_remove_doubles);
|
||||||
|
WM_operatortype_append(PARTICLE_OT_weight_set);
|
||||||
WM_operatortype_append(PARTICLE_OT_delete);
|
WM_operatortype_append(PARTICLE_OT_delete);
|
||||||
WM_operatortype_append(PARTICLE_OT_mirror);
|
WM_operatortype_append(PARTICLE_OT_mirror);
|
||||||
|
|
||||||
@ -111,6 +112,8 @@ static void keymap_particle(wmKeyConfig *keyconf)
|
|||||||
RNA_enum_set(WM_keymap_add_item(keymap, "PARTICLE_OT_brush_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
|
RNA_enum_set(WM_keymap_add_item(keymap, "PARTICLE_OT_brush_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
|
||||||
|
|
||||||
WM_keymap_add_menu(keymap, "VIEW3D_MT_particle_specials", WKEY, KM_PRESS, 0, 0);
|
WM_keymap_add_menu(keymap, "VIEW3D_MT_particle_specials", WKEY, KM_PRESS, 0, 0);
|
||||||
|
|
||||||
|
WM_keymap_add_item(keymap, "PARTICLE_OT_weight_set", KKEY, KM_PRESS, KM_SHIFT, 0);
|
||||||
|
|
||||||
ED_object_generic_keymap(keyconf, keymap, 1);
|
ED_object_generic_keymap(keyconf, keymap, 1);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user