Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h3
-rw-r--r--source/blender/blenkernel/BKE_paint.h3
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c117
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c40
-rw-r--r--source/blender/blenkernel/intern/paint.c6
-rw-r--r--source/blender/editors/armature/editarmature.c66
-rw-r--r--source/blender/editors/armature/meshlaplacian.c18
-rw-r--r--source/blender/editors/include/ED_mesh.h4
-rw-r--r--source/blender/editors/include/ED_view3d.h3
-rw-r--r--source/blender/editors/interface/interface_templates.c6
-rw-r--r--source/blender/editors/mesh/editmesh.c93
-rw-r--r--source/blender/editors/mesh/editmesh_mods.c2
-rw-r--r--source/blender/editors/object/object_intern.h6
-rw-r--r--source/blender/editors/object/object_ops.c6
-rw-r--r--source/blender/editors/object/object_vgroup.c620
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c11
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h4
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c13
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c24
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c628
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c99
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c198
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h2
-rw-r--r--source/blender/makesdna/DNA_object_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_internal.h2
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c28
-rw-r--r--source/blender/makesrna/intern/rna_object.c15
-rw-r--r--source/blender/makesrna/intern/rna_scene.c8
32 files changed, 1955 insertions, 93 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 46b533f33fd..a3e6c081fb7 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -222,6 +222,9 @@ struct DerivedMesh {
/* Draw all vertices as bgl points (no options) */
void (*drawVerts)(DerivedMesh *dm);
+ /* Jason Draw all selected vertices as bgl points (no options) */
+ void (*drawSelectedVerts)(DerivedMesh *dm);
+
/* Draw edges in the UV mesh (if exists) */
void (*drawUVEdges)(DerivedMesh *dm);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index ef16129e1e7..cee97e7631f 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -59,7 +59,8 @@ void paint_brush_set(struct Paint *paint, struct Brush *br);
* Texture paint could be removed since selected faces are not used
* however hiding faces is useful */
int paint_facesel_test(struct Object *ob);
-
+/* Jason */
+int paint_vertsel_test(struct Object *ob);
/* Session data (mode-specific) */
typedef struct SculptSession {
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index c84bcaabbd3..941a1516896 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -40,6 +40,9 @@
#include "DNA_cloth_types.h"
#include "DNA_key_types.h"
#include "DNA_meshdata_types.h"
+// Jason
+#include "DNA_armature_types.h"
+
#include "DNA_object_types.h"
#include "DNA_scene_types.h" // N_T
@@ -72,6 +75,8 @@
#include "GPU_material.h"
#include "ED_sculpt.h" /* for ED_sculpt_modifiers_changed */
+// Jason was here, this is for multi-paint
+#include "ED_armature.h"
///////////////////////////////////
///////////////////////////////////
@@ -1603,19 +1608,50 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb)
}
}
-static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col)
+static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col, char *dg_flags, int selected, int unselected, int multipaint, int auto_normalize)
{
Mesh *me = ob->data;
- float colf[4], input = 0.0f;
+ float colf[4], input = 0.0f;// Jason
int i;
+ char make_black = FALSE;
+ char was_a_nonzero = FALSE;
if (me->dvert) {
- for (i=0; i<me->dvert[vert].totweight; i++)
- if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
- input+=me->dvert[vert].dw[i].weight;
- }
+ for (i=0; i<me->dvert[vert].totweight; i++) {
+ // Jason was here
+ // in multipaint, get the average if auto normalize is inactive
+ // get the sum if it is active
+ if(multipaint && selected > 1) {
+ if(dg_flags[me->dvert[vert].dw[i].def_nr]) {
+ if(me->dvert[vert].dw[i].weight) {
+ input+=me->dvert[vert].dw[i].weight;
+ was_a_nonzero = TRUE;
+ }
+ }
+ } else if (me->dvert[vert].dw[i].def_nr==ob->actdef-1) {
+ input+=me->dvert[vert].dw[i].weight;
+ }
+ }
+
+ // Jason was here
+ // make it black if the selected groups have no weight on a vertex
+ if(!make_black && multipaint && selected > 1) {
+ if(!was_a_nonzero) {
+ make_black = TRUE;
+ } else if (!auto_normalize){
+ // get the average
+ input /= selected;
+ }
- CLAMP(input, 0.0f, 1.0f);
+ }
+ }
+
+ if(make_black) {
+ input = -1;
+ }else {
+ CLAMP(input, 0.0f, 1.0f);
+ }
+
if(coba)
do_colorband(coba, input, colf);
@@ -1634,26 +1670,69 @@ void vDM_ColorBand_store(ColorBand *coba)
{
stored_cb= coba;
}
-
-static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm)
+/* TODO move duplicates to header */
+/* Jason was here duplicate function in paint_vertex.c*/
+static char* get_selected_defgroups(Object *ob, int defcnt) {
+ bPoseChannel *chan;
+ bPose *pose;
+ bDeformGroup *defgroup;
+ //Bone *bone;
+ char *dg_flags = MEM_callocN(defcnt*sizeof(char), "dg_selected_flags");
+ int i;
+ Object *armob = ED_object_pose_armature(ob);
+
+ if(armob) {
+ pose = armob->pose;
+ for (chan=pose->chanbase.first; chan; chan=chan->next) {
+ for (i = 0, defgroup = ob->defbase.first; i < defcnt && defgroup; defgroup = defgroup->next, i++) {
+ if(!strcmp(defgroup->name, chan->bone->name)) {
+ dg_flags[i] = (chan->bone->flag & BONE_SELECTED);
+ }
+ }
+ }
+ }
+
+ return dg_flags;
+}
+/* TODO move duplicates to header */
+/* Jason was here duplicate function */
+static int count_true(char *list, int len)
+{
+ int i;
+ int cnt = 0;
+ for(i = 0; i < len; i++) {
+ if (list[i]) {
+ cnt++;
+ }
+ }
+ return cnt;
+}
+static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int multipaint, int auto_normalize)
{
Mesh *me = ob->data;
MFace *mf = me->mface;
ColorBand *coba= stored_cb; /* warning, not a local var */
unsigned char *wtcol;
int i;
-
+ // Jason was here
+ int defcnt = BLI_countlist(&ob->defbase);
+ char *dg_flags = get_selected_defgroups(ob, defcnt);
+ int selected = count_true(dg_flags, defcnt);
+ int unselected = defcnt - selected;
+
wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
for (i=0; i<me->totface; i++, mf++) {
- calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]);
- calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]);
- calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]);
+ calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4], dg_flags, selected, unselected, multipaint, auto_normalize);
+ calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4], dg_flags, selected, unselected, multipaint, auto_normalize);
+ calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4], dg_flags, selected, unselected, multipaint, auto_normalize);
if (mf->v4)
- calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]);
+ calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4], dg_flags, selected, unselected, multipaint, auto_normalize);
}
-
+ // Jason
+ MEM_freeN(dg_flags);
+
CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData);
}
@@ -1860,7 +1939,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
- add_weight_mcol_dm(ob, dm);
+ add_weight_mcol_dm(ob, dm, scene->toolsettings->multipaint, scene->toolsettings->auto_normalize);// Jason
/* Constructive modifiers need to have an origindex
* otherwise they wont have anywhere to copy the data from.
@@ -1972,7 +2051,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
CDDM_calc_normals(finaldm);
if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
- add_weight_mcol_dm(ob, finaldm);
+ add_weight_mcol_dm(ob, finaldm, scene->toolsettings->multipaint, scene->toolsettings->auto_normalize);// Jason
} else if(dm) {
finaldm = dm;
} else {
@@ -1984,7 +2063,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
- add_weight_mcol_dm(ob, finaldm);
+ add_weight_mcol_dm(ob, finaldm, scene->toolsettings->multipaint, scene->toolsettings->auto_normalize);// Jason
}
/* add an orco layer if needed */
@@ -2257,7 +2336,7 @@ static void clear_mesh_caches(Object *ob)
static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
{
Object *obact = scene->basact?scene->basact->object:NULL;
- int editing = paint_facesel_test(ob);
+ int editing = paint_facesel_test(ob) || paint_vertsel_test(ob);// Jason: paint_vertsel_test
/* weight paint and face select need original indices because of selection buffer drawing */
int needMapping = (ob==obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT|OB_MODE_VERTEX_PAINT)));
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 12fb11c68b3..5c7ffa5adc3 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -268,6 +268,44 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
}
+// Jason
+static void cdDM_drawSelectedVerts(DerivedMesh *dm)
+{
+ CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
+ MVert *mv = cddm->mvert;
+ int i;
+ if( GPU_buffer_legacy(dm) ) {
+ char prev_sel= 0; /* always invalid */;
+
+ glBegin(GL_POINTS);
+ for(i = 0; i < dm->numVertData; i++, mv++) {
+ if(!(mv->flag & ME_HIDE)) {
+ const char sel= mv->flag & 1;
+ if(prev_sel != sel) {
+ prev_sel= sel;
+
+ // TODO define selected color
+ if(sel) {
+ glColor3f(1.0f, 1.0f, 0.0f);
+ }else {
+ glColor3f(0.0f, 0.0f, 0.0f);
+ }
+ }
+
+ glVertex3fv(mv->co);
+ }
+ }
+ glEnd();
+ }
+ else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+ GPU_vertex_setup(dm);
+ if( !GPU_buffer_legacy(dm) ) {
+ if(dm->drawObject->tot_triangle_point) glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point);
+ else glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point);
+ }
+ GPU_buffer_unbind();
+ }
+}
static void cdDM_drawVerts(DerivedMesh *dm)
{
@@ -1535,6 +1573,8 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getFaceMap = cdDM_getFaceMap;
dm->drawVerts = cdDM_drawVerts;
+ // Jason
+ dm->drawSelectedVerts = cdDM_drawSelectedVerts;
dm->drawUVEdges = cdDM_drawUVEdges;
dm->drawEdges = cdDM_drawEdges;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index d00eb6192da..eac98519fcc 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -96,7 +96,11 @@ int paint_facesel_test(Object *ob)
{
return (ob && ob->type==OB_MESH && ob->data && (((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_MASK) && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT)));
}
-
+/* Jason */
+int paint_vertsel_test(Object *ob)
+{
+ return (ob && ob->type==OB_MESH && ob->data && (((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) && (ob->mode & OB_MODE_WEIGHT_PAINT));
+}
void paint_init(Paint *p, const char col[3])
{
Brush *brush;
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index 628cdbf21e9..cfe639578dc 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -4258,28 +4258,69 @@ static int bone_looper(Object *ob, Bone *bone, void *data,
return count;
}
+// Jason
+Bone* get_other_selected_bone(Object *ob) {
+ Bone *bone;
+ int i;
+ bone = get_indexed_bone(ob, 0);
+ for(i = 0; bone;){
+ if(bone->flag & BONE_SELECTED) {
+ return bone;
+ }
+ i++;
+ bone = get_indexed_bone(ob, i);
+ }
+ return NULL;
+}
/* called from editview.c, for mode-less pose selection */
/* assumes scene obact and basact is still on old situation */
int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short extend)
{
Object *ob= base->object;
Bone *nearBone;
-
+ // Jason
+ Bone *new_act_bone;
+
if (!ob || !ob->pose) return 0;
nearBone= get_bone_from_selectbuffer(scene, base, buffer, hits, 1);
-
+
/* if the bone cannot be affected, don't do anything */
if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
bArmature *arm= ob->data;
/* since we do unified select, we don't shift+select a bone if the armature object was not active yet */
- if (!(extend) || (base != scene->basact)) {
- ED_pose_deselectall(ob, 0);
- nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
- arm->act_bone= nearBone;
-
+ /* Jason was here, I'm doing a select for multibone painting */
+ if ((base != scene->basact)) {//if (!(extend) || (base != scene->basact)) {
+ /* Jason was here */
+ /* only deselect all if they aren't using 'shift' */
+ if(!extend) {
+ ED_pose_deselectall(ob, 0);
+ nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ arm->act_bone= nearBone;
+ ED_vgroup_select_by_name(OBACT, nearBone->name);
+ }
+ else {
+ // Jason deselect this bone specifically if it is selected already
+ if (nearBone->flag & BONE_SELECTED) {
+ nearBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ if(nearBone == arm->act_bone) {
+ // make a different bone the active one if it exists
+ new_act_bone = get_other_selected_bone(ob);
+ if(new_act_bone) {
+ new_act_bone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ arm->act_bone = new_act_bone;
+ ED_vgroup_select_by_name(OBACT, new_act_bone->name);
+ }
+ }
+ // or select the bone if they are using shift
+ } else {
+ nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
+ arm->act_bone= nearBone;
+ }
+ }
+ DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
// XXX old cruft! use notifiers instead
//select_actionchannel_by_name(ob->action, nearBone->name, 1);
}
@@ -5043,6 +5084,10 @@ void POSE_OT_select_inverse(wmOperatorType *ot)
static int pose_de_select_all_exec(bContext *C, wmOperator *op)
{
int action = RNA_enum_get(op->ptr, "action");
+ //Jason
+ Object *ob = NULL;
+ Scene *scene= CTX_data_scene(C);
+ int multipaint = scene->toolsettings->multipaint;
if (action == SEL_TOGGLE) {
action= CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
@@ -5072,7 +5117,12 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, NULL);
-
+ // Jason
+ if(multipaint) {
+ ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index b99605e65c1..0c2f8ca2ed4 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -657,22 +657,26 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
int *vertsflipped = NULL, *mask= NULL;
int a, totface, j, bbone, firstsegment, lastsegment;
+ // Jason
+ MVert *mv = me->mvert;
+ int selectedVerts;
+
*err_str= NULL;
/* count triangles and create mask */
- if(me->editflag & ME_EDIT_PAINT_MASK)
+ if((me->editflag & ME_EDIT_PAINT_MASK) || (selectedVerts=(me->editflag & ME_EDIT_VERT_SEL)))
mask= MEM_callocN(sizeof(int)*me->totvert, "heat_bone_weighting mask");
for(totface=0, a=0, mface=me->mface; a<me->totface; a++, mface++) {
totface++;
if(mface->v4) totface++;
-
- if(mask && (mface->flag & ME_FACE_SEL)) {
- mask[mface->v1]= 1;
- mask[mface->v2]= 1;
- mask[mface->v3]= 1;
+ // Jason (added selectedVerts content for vertex mask, they used to just equal 1)
+ if(mask && ((mface->flag & ME_FACE_SEL) || selectedVerts)) {
+ mask[mface->v1]= selectedVerts ? ((mv+mface->v1)->flag & 1): 1;
+ mask[mface->v2]= selectedVerts ? ((mv+mface->v2)->flag & 1): 1;
+ mask[mface->v3]= selectedVerts ? ((mv+mface->v3)->flag & 1): 1;
if(mface->v4)
- mask[mface->v4]= 1;
+ mask[mface->v4]= selectedVerts ? ((mv+mface->v4)->flag & 1): 1;
}
}
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 8bb77ad43a0..8005032f0a5 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -122,7 +122,9 @@ int EM_texFaceCheck(struct EditMesh *em);
int EM_vertColorCheck(struct EditMesh *em);
void undo_push_mesh(struct bContext *C, const char *name);
-
+/* Jason */
+void paintvert_flush_flags(struct Object *ob);
+void paintvert_deselect_all_visible(struct Object *ob, int action, short flush_flags);
/* editmesh_lib.c */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index dfe0a304748..62feeb151fa 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -215,6 +215,9 @@ void ED_view3d_project_float(struct ARegion *a, const float vec[3], float adr[2]
void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, struct rctf *viewborder_r, short do_shift);
/* drawobject.c iterators */
+/*Jason*/
+void mesh_obmode_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct MVert *mv, int x, int y, int index), void *userData, int clipVerts);
+
void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts);
void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts);
void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct EditFace *efa, int x, int y, int index), void *userData);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 2faac24fd78..ff64ba6db9d 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -2127,6 +2127,12 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
//uiItemR(row, itemptr, "mute", 0, "", ICON_MUTE_IPO_OFF);
uiBlockSetEmboss(block, UI_EMBOSS);
}
+ /* Jason was here: I need the RNA struct for vertex groups */
+ else if(RNA_struct_is_a(itemptr->type, &RNA_VertexGroup)) {
+ uiItemL(sub, name, icon);
+ uiBlockSetEmboss(block, UI_EMBOSS);
+ uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "flag", 0, 0, 0, 0, 0, NULL);
+ }
else
uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c
index 4377fb03632..132db6caaeb 100644
--- a/source/blender/editors/mesh/editmesh.c
+++ b/source/blender/editors/mesh/editmesh.c
@@ -1958,3 +1958,96 @@ void em_setup_viewcontext(bContext *C, ViewContext *vc)
vc->em= me->edit_mesh;
}
}
+
+
+/* Jason (similar to void paintface_flush_flags(Object *ob))
+ * copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
+ * use in object mode when selecting vertices (while painting) */
+void paintvert_flush_flags(Object *ob)
+{
+ Mesh *me= get_mesh(ob);
+ DerivedMesh *dm= ob->derivedFinal;
+ MVert *verts, *mv, *mv_orig;
+ int *index_array = NULL;
+ int totvert;
+ int i;
+
+ if(me==NULL || dm==NULL)
+ return;
+
+ index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
+
+ verts = dm->getVertArray(dm);
+ totvert = dm->getNumVerts(dm);
+
+ mv= verts;
+
+ for (i= 0; i<totvert; i++, mv++) { /* loop over derived mesh faces */
+ if(index_array) {
+ mv_orig= me->mvert + index_array[i];
+ mv->flag= mv_orig->flag;
+ } else {
+ mv_orig= me->mvert + i;
+ mv->flag= mv_orig->flag;
+ }
+ }
+}
+/* Jason note: caller needs to run paintvert_flush_flags(ob) after this */
+void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
+{
+ Mesh *me;
+ MVert *mvert;
+ int a;
+
+ me= get_mesh(ob);
+ if(me==NULL) return;
+
+ if(action == SEL_INVERT) {
+ mvert= me->mvert;
+ a= me->totvert;
+ while(a--) {
+ if((mvert->flag & ME_HIDE) == 0) {
+ mvert->flag ^= SELECT;
+ }
+ mvert++;
+ }
+ }
+ else {
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+
+ mvert= me->mvert;
+ a= me->totvert;
+ while(a--) {
+ if((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
+ action = SEL_DESELECT;
+ break;
+ }
+ mvert++;
+ }
+ }
+
+ mvert= me->mvert;
+ a= me->totvert;
+ while(a--) {
+ if((mvert->flag & ME_HIDE) == 0) {
+ switch (action) {
+ case SEL_SELECT:
+ mvert->flag |= SELECT;
+ break;
+ case SEL_DESELECT:
+ mvert->flag &= ~SELECT;
+ break;
+ case SEL_INVERT:
+ mvert->flag ^= SELECT;
+ break;
+ }
+ }
+ mvert++;
+ }
+ }
+
+ if(flush_flags) {
+ paintvert_flush_flags(ob);
+ }
+} \ No newline at end of file
diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c
index eb6854d2548..7f82cf0ff3b 100644
--- a/source/blender/editors/mesh/editmesh_mods.c
+++ b/source/blender/editors/mesh/editmesh_mods.c
@@ -266,6 +266,7 @@ int EM_mask_init_backbuf_border(ViewContext *vc, int mcords[][2], short tot, sho
/* method in use for face selecting too */
if(vc->obedit==NULL) {
if(paint_facesel_test(vc->obact));
+ else if(paint_vertsel_test(vc->obact));//Jason
else return 0;
}
else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
@@ -328,6 +329,7 @@ int EM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads)
/* method in use for face selecting too */
if(vc->obedit==NULL) {
if(paint_facesel_test(vc->obact));
+ else if (paint_vertsel_test(vc->obact));//Jason
else return 0;
}
else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 801880f0f32..e548e68d683 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -199,6 +199,12 @@ void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_normalize_all(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_levels(struct wmOperatorType *ot);
+/* Jason was here */
+void OBJECT_OT_vertex_group_lock_all(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_invert_locks(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_unlock_all(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_fix(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_clean(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index ff9b13379a2..ad08f08696c 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -173,6 +173,12 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_group_copy);
WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
+ /* Jason was here */
+ WM_operatortype_append(OBJECT_OT_vertex_group_invert_locks);
+ WM_operatortype_append(OBJECT_OT_vertex_group_lock_all);
+ WM_operatortype_append(OBJECT_OT_vertex_group_unlock_all);
+ WM_operatortype_append(OBJECT_OT_vertex_group_fix);
+
WM_operatortype_append(OBJECT_OT_vertex_group_invert);
WM_operatortype_append(OBJECT_OT_vertex_group_levels);
WM_operatortype_append(OBJECT_OT_vertex_group_blend);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 52ba9460818..8d2a584646a 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -60,6 +60,7 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
+#include "BKE_DerivedMesh.h"//Jason
#include "RNA_access.h"
#include "RNA_define.h"
@@ -701,6 +702,10 @@ static void vgroup_normalize(Object *ob)
MDeformWeight *dw;
MDeformVert *dvert, **dvert_array=NULL;
int i, def_nr, dvert_tot=0;
+ // Jason
+ Mesh *me = ob->data;
+ MVert *mv = me->mvert;
+ int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
@@ -712,6 +717,11 @@ static void vgroup_normalize(Object *ob)
def_nr= ob->actdef-1;
for(i = 0; i < dvert_tot; i++) {
+ // Jason
+ if(selectedVerts && !((mv+i)->flag & SELECT)) {
+ continue;
+ }
+
dvert = dvert_array[i];
dw = defvert_find_index(dvert, def_nr);
if(dw) {
@@ -721,6 +731,11 @@ static void vgroup_normalize(Object *ob)
if(weight_max > 0.0f) {
for(i = 0; i < dvert_tot; i++) {
+ // Jason
+ if(selectedVerts && !((mv+i)->flag & SELECT)) {
+ continue;
+ }
+
dvert = dvert_array[i];
dw = defvert_find_index(dvert, def_nr);
if(dw) {
@@ -735,6 +750,418 @@ static void vgroup_normalize(Object *ob)
if (dvert_array) MEM_freeN(dvert_array);
}
+// Jason
+/* This adds the indices of vertices to a list if they are not already present
+It returns the number that it added (0-2)
+It relies on verts having -1 for unassigned indices
+*/
+static int tryToAddVerts(int *verts, int length, int a, int b) {
+ char containsA = FALSE;
+ char containsB = FALSE;
+ int added = 0;
+ int i;
+ for(i = 0; i < length && (!containsA || !containsB); i++) {
+ if(verts[i] == a) {
+ containsA = TRUE;
+ } else if(verts[i] == b) {
+ containsB = TRUE;
+ } else if(verts[i] == -1) {
+ if(!containsA) {
+ verts[i] = a;
+ containsA = TRUE;
+ added++;
+ } else if(!containsB){
+ verts[i] = b;
+ containsB = TRUE;
+ added++;
+ }
+ }
+ }
+ return added;
+}
+//Jason
+/* This finds all of the vertices connected to vert by an edge
+and returns an array of indices of size count
+
+count is an int passed by reference so it can be assigned the value of the length here.
+*/
+static int* getSurroundingVerts(Mesh *me, int vert, int *count) {
+ int length = 0;
+ int *tverts;
+ int *verts = NULL;
+ MFace *mf = me->mface;
+ int totface = me->totface;
+ int found = 0;
+ int i;
+ for(i = 0; i < totface; i++, mf++) {
+ if(vert == mf->v1 || vert == mf->v2 || vert == mf->v3 || (mf->v4 &&vert == mf->v4)) {
+ length+=2;
+ }
+ }
+ if(!length) {
+ return 0;
+ }
+ tverts = MEM_mallocN(sizeof(int)*length, "tempSurroundingVerts");
+ mf = me->mface;
+ for(i = 0; i < length; i++) {
+ tverts[i] = -1;
+ }
+ for(i = 0; i < totface; i++, mf++) {
+ int a=-1, b=-1;
+ if(mf->v1 == vert) {
+ a = mf->v2;
+ if(mf->v4) {
+ b = mf->v4;
+ } else {
+ b = mf->v3;
+ }
+ } else if(mf->v2 == vert) {
+ a = mf->v1;
+ b = mf->v3;
+ } else if(mf->v3 == vert) {
+ a = mf->v2;
+ if(mf->v4) {
+ b = mf->v4;
+ } else {
+ b = mf->v1;
+ }
+ } else if (mf->v4 && mf->v4 == vert){
+ a = mf->v1;
+ b = mf->v3;
+ } else {
+ continue;
+ }
+ found += tryToAddVerts(tverts, length, a, b);
+ }
+ if(found) {
+ verts = MEM_mallocN(sizeof(int)* found, "surroundingVerts");
+ for(i = 0; i < found; i++) {
+ verts[i] = tverts[i];
+ }
+ *count = found;
+ }
+ MEM_freeN(tverts);
+ return verts;
+}
+/* Jason */
+/* get a single point in space by averaging a point cloud (vectors of size 3)
+coord is the place the average is stored, points is the point cloud, count is the number of points in the cloud
+*/
+static void getSingleCoordinate(MVert **points, int count, float *coord) {
+ int i, k;
+ for(k = 0; k < 3; k++) {
+ coord[k] = 0;
+ }
+ for(i = 0; i < count; i++) {
+ for(k = 0; k < 3; k++) {
+ coord[k] += points[i]->co[k];
+ }
+ }
+ for(k = 0; k < 3; k++) {
+ coord[k] /= count;
+ }
+}
+/* Jason */
+/* find the closest point on a plane to another point and store it in dst */
+/* coord is a point on the plane */
+/* point is the point that you want the nearest of */
+/* norm is the plane's normal, and d is the last number in the plane equation 0 = ax + by + cz + d */
+static void getNearestPointOnPlane(float *norm, float d, float *coord, float *point, float *dst) {
+ float *temp = MEM_callocN(sizeof(float)*3, "temp");
+ int i;
+ float dotprod = 0;
+ for(i = 0; i < 3; i++) {
+ temp[i] = point[i]-coord[i];
+ }
+ for(i = 0; i < 3; i++) {
+ dotprod += temp[i]*norm[i];
+ }
+ MEM_freeN(temp);
+ for(i = 0; i < 3; i++) {
+ dst[i] = point[i] - dotprod*norm[i];
+ }
+}
+/* Jason */
+/* distance of two vectors a and b of size length */
+static float distance(float* a, float *b, int length) {
+ int i;
+ float sum = 0;
+ for(i = 0; i < length; i++) {
+ sum += (b[i]-a[i])*(b[i]-a[i]);
+ }
+ return sqrt(sum);
+}
+/* Jason */
+/* given a plane and a start and end position,
+compute the amount of vertical distance relative to the plane and store it in dists,
+then get the horizontal and vertical change and store them in changes
+*/
+static void getVerticalAndHorizontalChange(float *norm, float d, float *coord, float *start, float distToStart, float *end, float **changes, float *dists, int index) {
+ // A=Q-((Q-P).N)N
+ // D = (a*x0 + b*y0 +c*z0 +d)
+ float *projA, *projB;
+ projA = MEM_callocN(sizeof(float)*3, "projectedA");
+ projB = MEM_callocN(sizeof(float)*3, "projectedB");
+ getNearestPointOnPlane(norm, d, coord, start, projA);
+ getNearestPointOnPlane(norm, d, coord, end, projB);
+ // (vertical and horizontal refer to the plane's y and xz respectively)
+ // vertical distance
+ dists[index] = norm[0]*end[0] + norm[1]*end[1] + norm[2]*end[2] + d;
+ // vertical change
+ changes[index][0] = dists[index] - distToStart;
+ //printf("vc %f %f\n", distance(end, projB, 3)-distance(start, projA, 3), changes[index][0]);
+ // horizontal change
+ changes[index][1] = distance(projA, projB, 3);
+
+ MEM_freeN(projA);
+ MEM_freeN(projB);
+}
+// Jason
+// I need the derived mesh to be forgotten so the positions are recalculated with weight changes (see dm_deform_recalc)
+static int dm_deform_clear(DerivedMesh *dm, Object *ob) {
+ dm->needsFree = 1;
+ dm->release(dm);
+ ob->derivedDeform=NULL;
+ // dm = NULL;
+ return NULL;
+}
+// Jason
+// recalculate the deformation
+static DerivedMesh* dm_deform_recalc(Scene *scene, Object *ob) {
+ return mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+}
+// Jason
+/* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to distToBe distance away from the provided plane
+strength can change distToBe so that it moves towards distToBe by that percentage
+cp changes how much the weights are adjusted to check the distance
+
+index is the index of the vertex being moved
+norm and d are the plane's properties for the equation: ax + by + cz + d = 0
+coord is a point on the plane
+*/
+static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, int index, float *norm, float *coord, float d, float distToBe, float strength, float cp) {
+ DerivedMesh *dm;
+ MDeformWeight *dw;
+ MVert m;
+ MDeformVert *dvert = me->dvert+index;
+ int totweight = dvert->totweight;
+ float oldw = 0;
+ float *oldPos = MEM_callocN(sizeof(float)*3, "oldPosition");
+ float vc, hc, dist;
+ int i, k;
+ float **changes = MEM_mallocN(sizeof(float *)*totweight, "vertHorzChange");
+ float *dists = MEM_mallocN(sizeof(float)*totweight, "distance");
+ int *upDown = MEM_callocN(sizeof(int)*totweight, "upDownTracker");// track if up or down moved it closer for each bone
+ int *dwIndices = MEM_callocN(sizeof(int)*totweight, "dwIndexTracker");
+ float distToStart;
+ int bestIndex = 0;
+ char wasChange;
+ char wasUp;
+ int lastIndex = -1;
+ float originalDistToBe = distToBe;
+ for(i = 0; i < totweight; i++) {
+ changes[i] = MEM_callocN(sizeof(float)*2, "vertHorzChange_"+i);
+ }
+ do {
+ wasChange = FALSE;
+ dm = dm_deform_recalc(scene, ob);
+ dm->getVert(dm, index, &m);
+ oldPos[0] = m.co[0];
+ oldPos[1] = m.co[1];
+ oldPos[2] = m.co[2];
+ distToStart = norm[0]*oldPos[0] + norm[1]*oldPos[1] + norm[2]*oldPos[2] + d;
+
+ if(distToBe == originalDistToBe) {
+ distToBe += distToStart - distToStart*strength;
+ }
+ for(i = 0; i < totweight; i++) {
+ dwIndices[i] = i;
+ dw = (dvert->dw+i);
+ vc = hc = 0;
+ if(!dw->weight) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ continue;
+ }
+ for(k = 0; k < 2; k++) {
+ if(dm) {
+ dm = dm_deform_clear(dm, ob);
+ }
+ oldw = dw->weight;
+ if(k) {
+ dw->weight *= 1+cp;
+ } else {
+ dw->weight /= 1+cp;
+ }
+ if(dw->weight == oldw) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ break;
+ }
+ if(dw->weight > 1) {
+ dw->weight = 1;
+ }
+ dm = dm_deform_recalc(scene, ob);
+ dm->getVert(dm, index, &m);
+ getVerticalAndHorizontalChange(norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
+ dw->weight = oldw;
+ if(!k) {
+ vc = changes[i][0];
+ hc = changes[i][1];
+ dist = dists[i];
+ } else {
+ if(fabs(dist - distToBe) < fabs(dists[i] - distToBe)) {
+ upDown[i] = 0;
+ changes[i][0] = vc;
+ changes[i][1] = hc;
+ dists[i] = dist;
+ } else {
+ upDown[i] = 1;
+ }
+ if(fabs(dists[i] - distToBe) > fabs(distToStart - distToBe)) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ }
+ }
+ }
+ }
+ // sort the changes by the vertical change
+ for(k = 0; k < totweight; k++) {
+ float tf;
+ int ti;
+ bestIndex = k;
+ for(i = k+1; i < totweight; i++) {
+ dist = dists[i];
+
+ if(fabs(dist) > fabs(dists[i])) {
+ bestIndex = i;
+ }
+ }
+ // switch with k
+ if(bestIndex != k) {
+ ti = upDown[k];
+ upDown[k] = upDown[bestIndex];
+ upDown[bestIndex] = ti;
+
+ ti = dwIndices[k];
+ dwIndices[k] = dwIndices[bestIndex];
+ dwIndices[bestIndex] = ti;
+
+ tf = changes[k][0];
+ changes[k][0] = changes[bestIndex][0];
+ changes[bestIndex][0] = tf;
+
+ tf = changes[k][1];
+ changes[k][1] = changes[bestIndex][1];
+ changes[bestIndex][1] = tf;
+
+ tf = dists[k];
+ dists[k] = dists[bestIndex];
+ dists[bestIndex] = tf;
+ }
+ }
+ bestIndex = -1;
+ // find the best change with an acceptable horizontal change
+ for(i = 0; i < totweight; i++) {
+ if(fabs(changes[i][0]) > fabs(changes[i][1]*2.0f)) {
+ bestIndex = i;
+ break;
+ }
+ }
+ if(bestIndex != -1) {
+ wasChange = TRUE;
+ // it is a good place to stop if it tries to move the opposite direction
+ // (relative to the plane) of last time
+ if(lastIndex != -1) {
+ if(wasUp != upDown[bestIndex]) {
+ wasChange = FALSE;
+ }
+ }
+ lastIndex = bestIndex;
+ wasUp = upDown[bestIndex];
+ dw = (dvert->dw+dwIndices[bestIndex]);
+ oldw = dw->weight;
+ if(upDown[bestIndex]) {
+ dw->weight *= 1+cp;
+ } else {
+ dw->weight /= 1+cp;
+ }
+ if(dw->weight > 1) {
+ dw->weight = 1;
+ }
+ if(oldw == dw->weight) {
+ wasChange = FALSE;
+ }
+ if(dm) {
+ dm = dm_deform_clear(dm, ob);
+ }
+ }
+ }while(wasChange && (distToStart-distToBe)/fabs(distToStart-distToBe) == (dists[bestIndex]-distToBe)/fabs(dists[bestIndex]-distToBe));
+ MEM_freeN(upDown);
+ for(i = 0; i < totweight; i++) {
+ MEM_freeN(changes[i]);
+ }
+ MEM_freeN(changes);
+ MEM_freeN(dists);
+ MEM_freeN(dwIndices);
+ MEM_freeN(oldPos);
+}
+// Jason
+/* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex
+but it could be used to raise or lower an existing 'bump.' */
+static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength, float cp)
+{
+ int i;
+
+ Mesh *me = ob->data;
+ MVert *mv = me->mvert;
+ int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
+ int *verts = NULL;
+ for(i = 0; i < me->totvert && mv; i++, mv++) {
+ // Jason
+ if(selectedVerts && (mv->flag & SELECT)) {
+
+ int count=0;
+ if((verts = getSurroundingVerts(me, i, &count))) {
+ MVert m;
+ MVert **p = MEM_callocN(sizeof(MVert*)*(count), "deformedPoints");
+ int k;
+
+ DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ for(k = 0; k < count; k++) {
+ dm->getVert(dm, verts[k], &m);
+ p[k] = &m;
+ }
+
+ if(count >= 3) {
+ float d, dist, mag;
+ float *coord = MEM_callocN(sizeof(float)*3, "deformedCoord");
+ float *norm = MEM_callocN(sizeof(float)*3, "planeNorm");
+ getSingleCoordinate(p, count, coord);
+ dm->getVert(dm, i, &m);
+ norm[0] = m.co[0]-coord[0];
+ norm[1] = m.co[1]-coord[1];
+ norm[2] = m.co[2]-coord[2];
+ mag = sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
+ for(k = 0; k < 3; k++) {
+ norm[k]/=mag;
+ }
+ d = -norm[0]*coord[0] -norm[1]*coord[1] -norm[2]*coord[2];
+ dist = (norm[0]*m.co[0] + norm[1]*m.co[1] + norm[2]*m.co[2] + d);
+ moveCloserToDistanceFromPlane(scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
+ MEM_freeN(coord);
+ MEM_freeN(norm);
+ }
+
+ MEM_freeN(verts);
+ MEM_freeN(p);
+ }
+ }
+ }
+}
static void vgroup_levels(Object *ob, float offset, float gain)
{
@@ -742,7 +1169,11 @@ static void vgroup_levels(Object *ob, float offset, float gain)
MDeformWeight *dw;
MDeformVert *dvert, **dvert_array=NULL;
int i, def_nr, dvert_tot=0;
-
+ // Jason
+ Mesh *me = ob->data;
+ MVert *mv = me->mvert;
+ int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
+
ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
@@ -751,6 +1182,11 @@ static void vgroup_levels(Object *ob, float offset, float gain)
def_nr= ob->actdef-1;
for(i = 0; i < dvert_tot; i++) {
+ // Jason
+ if(selectedVerts && !((mv+i)->flag & SELECT)) {
+ continue;
+ }
+
dvert = dvert_array[i];
dw = defvert_find_index(dvert, def_nr);
if(dw) {
@@ -772,6 +1208,11 @@ static void vgroup_normalize_all(Object *ob, int lock_active)
int i, dvert_tot=0;
float tot_weight;
+ // Jason
+ Mesh *me = ob->data;
+ MVert *mv = me->mvert;
+ int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
+
ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
if(dvert_array) {
@@ -781,6 +1222,10 @@ static void vgroup_normalize_all(Object *ob, int lock_active)
for(i = 0; i < dvert_tot; i++) {
float lock_iweight= 1.0f;
int j;
+ // Jason
+ if(selectedVerts && !((mv+i)->flag & SELECT)) {
+ continue;
+ }
tot_weight= 0.0f;
dw_act= NULL;
@@ -821,6 +1266,11 @@ static void vgroup_normalize_all(Object *ob, int lock_active)
else {
for(i = 0; i < dvert_tot; i++) {
int j;
+ // Jason
+ if(selectedVerts && !((mv+i)->flag & SELECT)) {
+ continue;
+ }
+
tot_weight= 0.0f;
dvert = dvert_array[i];
@@ -846,7 +1296,33 @@ static void vgroup_normalize_all(Object *ob, int lock_active)
if (dvert_array) MEM_freeN(dvert_array);
}
-
+/* Jason was here */
+static void vgroup_invert_locks(Object *ob)
+{
+ bDeformGroup *dg = ob->defbase.first;
+ while(dg) {
+ dg->flag = !dg->flag;
+ dg = dg->next;
+ }
+}
+/* Jason was here */
+static void vgroup_lock_all(Object *ob)
+{
+ bDeformGroup *dg = ob->defbase.first;
+ while(dg) {
+ dg->flag = TRUE;
+ dg = dg->next;
+ }
+}
+/* Jason was here */
+static void vgroup_unlock_all(Object *ob)
+{
+ bDeformGroup *dg = ob->defbase.first;
+ while(dg) {
+ dg->flag = FALSE;
+ dg = dg->next;
+ }
+}
static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
{
@@ -854,6 +1330,10 @@ static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
MDeformWeight *dw;
MDeformVert *dvert, **dvert_array=NULL;
int i, def_nr, dvert_tot=0;
+ // Jason
+ Mesh *me = ob->data;
+ MVert *mv = me->mvert;
+ int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
@@ -864,6 +1344,10 @@ static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
for(i = 0; i < dvert_tot; i++) {
+ // Jason
+ if(selectedVerts && !((mv+i)->flag & SELECT)) {
+ continue;
+ }
dvert = dvert_array[i];
if(auto_assign) {
@@ -976,6 +1460,10 @@ static void vgroup_clean(Object *ob, float eul, int keep_single)
MDeformWeight *dw;
MDeformVert *dvert, **dvert_array=NULL;
int i, def_nr, dvert_tot=0;
+ // Jason
+ Mesh *me = ob->data;
+ MVert *mv = me->mvert;
+ int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
@@ -985,6 +1473,10 @@ static void vgroup_clean(Object *ob, float eul, int keep_single)
def_nr= ob->actdef-1;
for(i = 0; i < dvert_tot; i++) {
+ // Jason
+ if(selectedVerts && !((mv+i)->flag & SELECT)) {
+ continue;
+ }
dvert = dvert_array[i];
dw= defvert_find_index(dvert, def_nr);
@@ -1006,12 +1498,21 @@ static void vgroup_clean_all(Object *ob, float eul, int keep_single)
MDeformWeight *dw;
MDeformVert *dvert, **dvert_array=NULL;
int i, dvert_tot=0;
+ // Jason
+ Mesh *me = ob->data;
+ MVert *mv = me->mvert;
+ int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
if(dvert_array) {
for(i = 0; i < dvert_tot; i++) {
int j;
+ // Jason
+ if(selectedVerts && !((mv+i)->flag & SELECT)) {
+ continue;
+ }
+
dvert = dvert_array[i];
j= dvert->totweight;
@@ -1831,7 +2332,122 @@ void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
}
+/* Jason */
+static int vertex_group_fix_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ Scene *scene= CTX_data_scene(C);
+
+ float distToBe= RNA_float_get(op->ptr,"dist");
+ float strength= RNA_float_get(op->ptr,"strength");
+ float cp= RNA_float_get(op->ptr,"cp");
+ ModifierData *md = ob->modifiers.first;
+
+ while(md) {
+ if(md->type == eModifierType_Mirror && (md->mode&eModifierMode_Realtime)) {
+ break;
+ }
+ md = md->next;
+ }
+
+ if(md && md->type == eModifierType_Mirror) {
+ BKE_report(op->reports, RPT_ERROR_INVALID_CONTEXT, "This operator does not support an active mirror modifier");
+ return OPERATOR_CANCELLED;
+ }
+ vgroup_fix(scene, ob, distToBe, strength, cp);
+
+ 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_GEOM|ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Fix Vertex Group Deform";
+ ot->idname= "OBJECT_OT_vertex_group_fix";
+
+ /* api callbacks */
+ ot->poll= vertex_group_poll;
+ ot->exec= vertex_group_fix_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+ RNA_def_float(ot->srna, "dist", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "The distance to move to.", -10.0f, 10.0f);
+ RNA_def_float(ot->srna, "strength", 1.f, -2.0f, FLT_MAX, "Strength", "The distance moved can be changed by this multiplier.", -2.0f, 2.0f);
+ RNA_def_float(ot->srna, "cp", 1.0f, 0.05f, FLT_MAX, "Change Sensitivity", "Changes the amount weights are altered with each iteration: lower values are slower.", 0.05f, 1.f);
+}
+/* Jason was here */
+static int vertex_group_invert_locks_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+
+ vgroup_invert_locks(ob);
+
+ return OPERATOR_FINISHED;
+}
+/* Jason was here */
+void OBJECT_OT_vertex_group_invert_locks(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Invert All Vertex Group Locks";
+ ot->idname= "OBJECT_OT_vertex_group_invert_locks";
+
+ /* api callbacks */
+ ot->poll= vertex_group_poll;
+ ot->exec= vertex_group_invert_locks_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+/* Jason was here */
+static int vertex_group_lock_all_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+
+ vgroup_lock_all(ob);
+
+ return OPERATOR_FINISHED;
+}
+/* Jason was here */
+void OBJECT_OT_vertex_group_lock_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Turn on all Vertex Group Locks";
+ ot->idname= "OBJECT_OT_vertex_group_lock_all";
+
+ /* api callbacks */
+ ot->poll= vertex_group_poll;
+ ot->exec= vertex_group_lock_all_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+/* Jason was here */
+static int vertex_group_unlock_all_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+
+ vgroup_unlock_all(ob);
+ return OPERATOR_FINISHED;
+}
+/* Jason was here */
+void OBJECT_OT_vertex_group_unlock_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Turn off all Vertex Group Locks";
+ ot->idname= "OBJECT_OT_vertex_group_unlock_all";
+
+ /* api callbacks */
+ ot->poll= vertex_group_poll;
+ ot->exec= vertex_group_unlock_all_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
static int vertex_group_invert_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 32004fd4525..3c3d3503771 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -5407,7 +5407,16 @@ int facemask_paint_poll(bContext *C)
{
return paint_facesel_test(CTX_data_active_object(C));
}
-
+// Jason
+int vert_paint_poll(bContext *C)
+{
+ return paint_vertsel_test(CTX_data_active_object(C));
+}
+// Jason
+int mask_paint_poll(bContext *C)
+{
+ return paint_facesel_test(CTX_data_active_object(C)) || paint_vertsel_test(CTX_data_active_object(C));
+}
/* use project paint to re-apply an image */
static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
{
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 5a0ee19d6c9..95a6d0c2732 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -121,6 +121,10 @@ void PAINT_OT_face_select_all(struct wmOperatorType *ot);
void PAINT_OT_face_select_inverse(struct wmOperatorType *ot);
void PAINT_OT_face_select_hide(struct wmOperatorType *ot);
void PAINT_OT_face_select_reveal(struct wmOperatorType *ot);
+/* Jason */
+void PAINT_OT_vert_select_all(struct wmOperatorType *ot);
+int vert_paint_poll(struct bContext *C);
+int mask_paint_poll(struct bContext *C);
int facemask_paint_poll(struct bContext *C);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 69af50415cc..6aab104b79a 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -373,6 +373,9 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_weight_sample);
WM_operatortype_append(PAINT_OT_weight_sample_group);
+ /* Jason, vertex selection */
+ WM_operatortype_append(PAINT_OT_vert_select_all);
+
/* vertex */
WM_operatortype_append(PAINT_OT_vertex_paint_toggle);
WM_operatortype_append(PAINT_OT_vertex_paint);
@@ -607,6 +610,16 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "PAINT_OT_weight_from_bones", WKEY, KM_PRESS, 0, 0);
+ // Jason
+ /*Weight paint's Vertex Selection Mode */
+ keymap= WM_keymap_find(keyconf, "Weight Paint Vertex Selection", 0, 0);
+ keymap->poll= vert_paint_poll;
+ WM_keymap_add_item(keymap, "PAINT_OT_vert_select_all", AKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_select_border", BKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
+ RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT|KM_CTRL, 0)->ptr, "deselect", 1);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_select_circle", CKEY, KM_PRESS, 0, 0);
+
/* Image/Texture Paint mode */
keymap= WM_keymap_find(keyconf, "Image Paint", 0, 0);
keymap->poll= image_texture_paint_poll;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 09f5c32bea0..18f59536092 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -358,6 +358,30 @@ void PAINT_OT_face_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
+/* Jason */
+static int vert_select_all_exec(bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ paintvert_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), TRUE);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ return OPERATOR_FINISHED;
+}
+
+/* Jason */
+void PAINT_OT_vert_select_all(wmOperatorType *ot)
+{
+ ot->name= "Vertex Selection";
+ ot->description= "Change selection for all vertices";
+ ot->idname= "PAINT_OT_vert_select_all";
+
+ ot->exec= vert_select_all_exec;
+ ot->poll= vert_paint_poll;
+
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ WM_operator_properties_select_all(ot);
+}
+
static int face_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob= CTX_data_active_object(C);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 3da19ba7346..31366701afc 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -362,7 +362,7 @@ void vpaint_fill(Object *ob, unsigned int paintcol)
MFace *mf;
unsigned int *mcol;
int i, selected;
-
+
me= get_mesh(ob);
if(me==NULL || me->totface==0) return;
@@ -398,11 +398,15 @@ void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
unsigned char i;
int vgroup_mirror= -1;
int selected;
-
+ // Jason
+ int selectedVerts;
+
me= ob->data;
if(me==NULL || me->totface==0 || me->dvert==NULL || !me->mface) return;
selected= (me->editflag & ME_EDIT_PAINT_MASK);
+ // Jason
+ selectedVerts = (me->editflag & ME_EDIT_VERT_SEL);
indexar= get_indexarray(me);
@@ -438,6 +442,11 @@ void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
faceverts[3]= mface->v4;
for (i=0; i<3 || faceverts[i]; i++) {
if(!((me->dvert+faceverts[i])->flag)) {
+ // Jason
+ if(selectedVerts && !((me->mvert+faceverts[i])->flag & SELECT)) {
+ continue;
+ }
+
dw= defvert_verify_index(me->dvert+faceverts[i], vgroup);
if(dw) {
uw= defvert_verify_index(wp->wpaint_prev+faceverts[i], vgroup);
@@ -792,7 +801,7 @@ static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], fl
return alpha;
}
-static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval, int flip)
+static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval, int flip, int multipaint)
{
Brush *brush = paint_brush(&wp->paint);
int tool = brush->vertexpaint_tool;
@@ -830,7 +839,8 @@ static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float
if (dw->weight > paintval)
dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
}
- CLAMP(dw->weight, 0.0f, 1.0f);
+ // Jason delay clamping until the end so multi-paint can function when the active group is at the limits
+ //CLAMP(dw->weight, 0.0f, 1.0f);
/* if no spray, clip result with orig weight & orig alpha */
if((wp->flag & VP_SPRAY)==0) {
@@ -857,15 +867,16 @@ static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float
else
testw = uw->weight;
}
- CLAMP(testw, 0.0f, 1.0f);
-
- if( testw<uw->weight ) {
- if(dw->weight < testw) dw->weight= testw;
- else if(dw->weight > uw->weight) dw->weight= uw->weight;
- }
- else {
- if(dw->weight > testw) dw->weight= testw;
- else if(dw->weight < uw->weight) dw->weight= uw->weight;
+ //CLAMP(testw, 0.0f, 1.0f);
+ if(!multipaint) {
+ if( testw<uw->weight ) {
+ if(dw->weight < testw) dw->weight= testw;
+ else if(dw->weight > uw->weight) dw->weight= uw->weight;
+ }
+ else {
+ if(dw->weight > testw) dw->weight= testw;
+ else if(dw->weight < uw->weight) dw->weight= uw->weight;
+ }
}
}
@@ -1096,15 +1107,474 @@ static void do_weight_paint_auto_normalize(MDeformVert *dvert,
}
}
}
+// Jason was here: the active group should be involved in auto normalize
+static void do_weight_paint_auto_normalize_all_groups(MDeformVert *dvert, char *map)
+{
+// MDeformWeight *dw = dvert->dw;
+ float sum=0.0f, fac=0.0f;
+ int i, tot=0;
+
+ if (!map)
+ return;
+
+ for (i=0; i<dvert->totweight; i++) {
+ if (map[dvert->dw[i].def_nr]) {
+ tot += 1;
+ sum += dvert->dw[i].weight;
+ }
+ }
+
+ if (!tot || sum == 1.0f)
+ return;
+
+ fac = sum;
+ fac = fac==0.0f ? 1.0f : 1.0f / fac;
+
+ for (i=0; i<dvert->totweight; i++) {
+ if (map[dvert->dw[i].def_nr]) {
+ dvert->dw[i].weight *= fac;
+ }
+ }
+}
+/* Jason was here */
+/*
+See if the current deform vertex has a locked group
+*/
+static char has_locked_group(MDeformVert *dvert, char *flags)
+{
+ int i;
+ for(i = 0; i < dvert->totweight; i++) {
+ if(flags[(dvert->dw+i)->def_nr] && (dvert->dw+i)->weight > 0.0f) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+/*Jason was here
+gen_lck_flags gets the status of "flag" for each bDeformGroup
+in ob->defbase and returns an array containing them
+*/
+static char* gen_lck_flags(Object* ob, int defcnt, char *map)
+{
+ char is_locked = FALSE;
+ int i;
+ //int defcnt = BLI_countlist(&ob->defbase);
+ char *flags = MEM_mallocN(defcnt*sizeof(char), "defflags");
+ bDeformGroup *defgroup;
+ int selected = 0;
+
+ for(i = 0, defgroup = ob->defbase.first; i < defcnt && defgroup; defgroup = defgroup->next, i++) {
+ flags[i] = defgroup->flag;
+ if(flags[i]) {
+ is_locked = TRUE;
+ }
+ }
+ if(is_locked){
+ return flags;
+ }
+ // don't forget to free it if it is unneeded
+ MEM_freeN(flags);
+ return NULL;
+}
+/* Jason was here */
+static int has_locked_group_selected(int defcnt, char *selection, char *flags) {
+ int i;
+ for(i = 0; i < defcnt; i++) {
+ if(selection[i] && flags[i]) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* Jason was here */
+static int has_unselected_unlocked_bone_group(int defcnt, char *selection, int selected, char *flags, char *bone_groups) {
+ int i;
+ if(defcnt == selected) {
+ return FALSE;
+ }
+ for(i = 0; i < defcnt; i++) {
+ if(bone_groups[i] && !selection[i] && !flags[i]) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*Jason*/
+static void multipaint_selection(MDeformVert *dvert, float change, char *selection, int defcnt) {
+ int i;
+ MDeformWeight *dw;
+ float val;
+ // make sure they are all at most 1 after the change
+ for(i = 0; i < defcnt; i++) {
+ if(selection[i]) {
+ dw = defvert_find_index(dvert, i);
+ if(dw && dw->weight) {
+ val = dw->weight * change;
+ if(val > 1) {
+ // Jason TODO: when the change is reduced, you need to recheck the earlier values to make sure they are not 0 (precision error)
+ change = 1.0f/dw->weight;
+ }
+ // the value should never reach zero while multi-painting if it was nonzero beforehand
+ if(val <= 0) {
+ return;
+ }
+ }
+ }
+ }
+ // apply the valid change
+ for(i = 0; i < defcnt; i++) {
+ if(selection[i]) {
+ dw = defvert_find_index(dvert, i);
+ if(dw && dw->weight) {
+ dw->weight = dw->weight * change;
+ }
+ }
+ }
+}
+/*Jason*/
+// move all change onto valid, unchanged groups. If there is change left over, then return it.
+// assumes there are valid groups to shift weight onto
+static float redistribute_change(MDeformVert *ndv, char *change_status, int changeme, int changeto, char *validmap, float totchange, float total_valid) {
+ float was_change;
+ float change;
+ float oldval;
+ MDeformWeight *ndw;
+ int i;
+ do {
+ // assume there is no change until you see one
+ was_change = FALSE;
+ // change each group by the same amount each time
+ change = totchange/total_valid;
+ for(i = 0; i < ndv->totweight && total_valid && totchange; i++) {
+ ndw = (ndv->dw+i);
+ // change only the groups with a valid status
+ if(change_status[ndw->def_nr] == changeme) {
+ oldval = ndw->weight;
+ // if auto normalize is active, don't worry about upper bounds
+ if(!validmap && ndw->weight + change > 1) {
+ totchange -= 1-ndw->weight;
+ ndw->weight = 1;
+ // stop the changes to this group
+ change_status[ndw->def_nr] = changeto;
+ total_valid--;
+ } else if(ndw->weight + change < 0) { // check the lower bound
+ totchange -= ndw->weight;
+ ndw->weight = 0;
+ change_status[ndw->def_nr] = changeto;
+ total_valid--;
+ } else {// a perfectly valid change occurred to ndw->weight
+ totchange -= change;
+ ndw->weight += change;
+ }
+ // see if there was a change
+ if(oldval != ndw->weight) {
+ was_change = TRUE;
+ }
+ }
+ }
+ // don't go again if there was no change, if there is no valid group, or there is no change left
+ }while(was_change && total_valid && totchange);
+ // left overs
+ return totchange;
+}
+/*Jason*/
+// observe the changes made to the weights of groups.
+// make sure all locked groups on the vertex have the same deformation
+// by moving the changes made to groups onto other unlocked groups
+static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, int defcnt, char *flags, char *bone_groups, char *validmap) {
+ float totchange = 0.0f;
+ float totchange_allowed = 0.0f;
+ float left_over;
+
+ int total_valid = 0;
+ int total_changed = 0;
+ int i;
+ MDeformWeight *ndw;
+ MDeformWeight *odw;
+ MDeformWeight *ndw2;
+ MDeformWeight *odw2;
+ int designatedw = -1;
+ int designatedw_changed = FALSE;
+ float storedw;
+ char *change_status;
+ char new_weight_has_zero = FALSE;
+
+ if(!flags || !has_locked_group(ndv, flags)) {
+ return;
+ }
+ // record if a group was changed, unlocked and not changed, or locked
+ change_status = MEM_callocN(sizeof(char)*defcnt, "unlocked_unchanged");
+
+ for(i = 0; i < defcnt; i++) {
+ ndw = defvert_find_index(ndv, i);
+ odw = defvert_find_index(odv, i);
+ // the weights are zero, so we can assume a lot
+ if(!ndw || !odw) {
+ if (!flags[i] && bone_groups[i]){
+ defvert_verify_index(odv, i);
+ defvert_verify_index(ndv, i);
+ total_valid++;
+ change_status[i] = 1; // can be altered while redistributing
+ }
+ continue;
+ }
+ // locked groups should not be changed
+ if(flags[i]) {
+ ndw->weight = odw->weight;
+ } else if(ndw->weight != odw->weight) { // changed groups are handled here
+ totchange += ndw->weight-odw->weight;
+ change_status[i] = 2; // was altered already
+ total_changed++;
+ if(ndw->weight == 0) {
+ new_weight_has_zero = TRUE;
+ } else if(designatedw == -1){
+ designatedw = i;
+ }
+ } // unchanged, unlocked bone groups are handled here
+ else if (bone_groups[i]){
+ totchange_allowed += ndw->weight;
+ total_valid++;
+ change_status[i] = 1; // can be altered while redistributing
+ }
+ }
+ // if there was any change, redistribute it
+ if(total_changed) {
+ // auto normalize will allow weights to temporarily go above 1 in redistribution
+ if(validmap && total_changed < 0 && total_valid) {
+ totchange_allowed = total_valid;
+ }
+ // there needs to be change allowed, or you should not bother
+ if(totchange_allowed) {
+ // the way you modify the unlocked+unchanged groups is different depending
+ // on whether or not you are painting the weight(s) up or down
+ if(totchange < 0) {
+ totchange_allowed = total_valid - totchange_allowed;
+ } else {
+ totchange_allowed *= -1;
+ }
+ left_over = 0;
+ if(fabs(totchange_allowed) < fabs(totchange)) {
+ // this amount goes back onto the changed, unlocked weights
+ left_over = fabs(fabs(totchange)-fabs(totchange_allowed));
+ if(totchange > 0) {
+ left_over *= -1;
+ }
+ }else {
+ // all of the change will be permitted
+ totchange_allowed = -totchange;
+ }
+ // move the weight evenly between the allowed groups, move excess back onto the used groups based on the change
+ totchange_allowed = redistribute_change(ndv, change_status, 1, -1, validmap, totchange_allowed, total_valid);
+ left_over += totchange_allowed;
+ if(left_over) {
+ // more than one nonzero weights were changed with the same ratio, so keep them changed that way!
+ if(total_changed > 1 && !new_weight_has_zero && designatedw >= 0) {
+ // this dw is special, it is used as a base to determine how to change the others
+ ndw = defvert_find_index(ndv, designatedw);
+ odw = defvert_find_index(odv, designatedw);
+ storedw = ndw->weight;
+ for(i = 0; i < ndv->totweight; i++) {
+ if(change_status[ndw->def_nr] == 2) {
+ odw2 = (odv->dw+i);
+ ndw2 = (ndv->dw+i);
+ if(!designatedw_changed) {
+ ndw->weight = (totchange_allowed + odw->weight + odw2->weight)/(1 + ndw2->weight/ndw->weight);
+ designatedw_changed = TRUE;
+ }
+ ndw2->weight = ndw->weight*ndw2->weight/storedw;
+ }
+ }
+ }
+ // a weight was changed to zero, only one weight was changed, or designatedw is still -1
+ // put weight back as evenly as possible
+ else {
+ redistribute_change(ndv, change_status, 2, -2, validmap, left_over, total_changed);
+ }
+ }
+ } else {
+ // reset the weights
+ for(i = 0; i < ndv->totweight; i++) {
+ (ndv->dw+i)->weight = (odv->dw+i)->weight;
+ }
+ }
+ }
+
+ MEM_freeN(change_status);
+}
+/*Jason*/
+// multi-paint's initial, potential change is computed here based on the user's stroke
+static float get_mp_change(MDeformVert *odv, char *selection, float brush_change) {
+ float selwsum = 0.0f;
+ int i;
+ MDeformWeight *dw;
+ for(i=0; i < odv->totweight; i++) {
+ if(selection[(dw = (odv->dw+i))->def_nr]) {
+ selwsum += dw->weight;
+ }
+ }
+ if(selwsum && selwsum+brush_change > 0) {
+ return (selwsum+brush_change)/selwsum;
+ }
+ return 0.0f;
+}
+/*Jason*/
+// change the weights back to the wv's weights
+// it assumes you already have the correct pointer index
+static void reset_to_prev(MDeformVert *wv, MDeformVert *dv) {
+ int i;
+ MDeformWeight *d;
+ MDeformWeight *w;
+ for(i = 0; i < dv->totweight; i++) {
+ d = dv->dw+i;
+ w = defvert_find_index(wv, d->def_nr);
+ // if there was no w when there is a d, then the old weight was 0
+ if(w) {
+ d->weight = w->weight;
+ } else {
+ d->weight = 0;
+ }
+ }
+}
+/* Jason */
+static void clamp_weights(MDeformVert *dvert) {
+ int i;
+ for (i = 0; i < dvert->totweight; i++) {
+ CLAMP((dvert->dw+i)->weight, 0.0f, 1.0f);
+ }
+}
+/*Jason*/
+/* fresh start to make multi-paint and locking modular */
+/* returns TRUE if it thinks you need to reset the weights due to normalizing while multi-painting */
+static int apply_mp_lcks_normalize(Object *ob, Mesh *me, int index, MDeformWeight *dw, MDeformWeight *tdw, int defcnt, float change, float oldChange, float oldw, float neww, char *selection, int selected, char *bone_groups, char *validmap, char *flags, int multipaint) {
+ MDeformVert *dvert = me->dvert+index;
+ MDeformVert *dv = MEM_mallocN(sizeof (*(me->dvert+index)), "oldMDeformVert");
+
+ dv->dw= MEM_dupallocN(dvert->dw);
+ dv->flag = dvert->flag;
+ dv->totweight = dvert->totweight;
+ // do not multi-paint if a locked group is selected or the active group is locked
+ // !flags[dw->def_nr] helps if nothing is selected, but active group is locked
+ if(!flags || flags && !has_locked_group_selected(defcnt, selection, flags) && !flags[dw->def_nr]) {
+ if(multipaint && selected > 1) {
+ if(change && change!=1) {
+ multipaint_selection(dvert, change, selection, defcnt);
+ }
+ } else {// this lets users paint normally, but don't let them paint locked groups
+ dw->weight = neww;
+ }
+ }
+ clamp_weights(dvert);
+
+ enforce_locks(dv, dvert, defcnt, flags, bone_groups, validmap);
+
+ do_weight_paint_auto_normalize_all_groups(dvert, validmap);
+
+ if(oldChange && multipaint && selected > 1) {
+ if(tdw->weight != oldw) {
+ if( neww > oldw ) {
+ if(tdw->weight <= oldw) {
+ MEM_freeN(dv->dw);
+ MEM_freeN(dv);
+ return TRUE;
+ }
+ } else {
+ if(tdw->weight >= oldw) {
+ MEM_freeN(dv->dw);
+ MEM_freeN(dv);
+ return TRUE;
+ }
+ }
+ }
+ }
+ MEM_freeN(dv->dw);
+ MEM_freeN(dv);
+ return FALSE;
+}
+
+/* Jason was here duplicate function I used in DerivedMesh.c*/
+static char* get_selected_defgroups(Object *ob, int defcnt) {
+ bPoseChannel *chan;
+ bPose *pose;
+ bDeformGroup *defgroup;
+ //Bone *bone;
+ char *dg_flags = MEM_callocN(defcnt*sizeof(char), "dg_selected_flags");
+ int i;
+ Object *armob = ED_object_pose_armature(ob);
+
+ if(armob) {
+ pose = armob->pose;
+ for (chan=pose->chanbase.first; chan; chan=chan->next) {
+ for (i = 0, defgroup = ob->defbase.first; i < defcnt && defgroup; defgroup = defgroup->next, i++) {
+ if(!strcmp(defgroup->name, chan->bone->name)) {
+ dg_flags[i] = (chan->bone->flag & BONE_SELECTED);
+ }
+ }
+ }
+ }
+ // the array has whether or not the corresponding group is selected
+ return dg_flags;
+}
+/* TODO move duplicates to header */
+/* Jason was here duplicate function */
+static int count_true(char *list, int len)
+{
+ int i;
+ int cnt = 0;
+ for(i = 0; i < len; i++) {
+ if (list[i]) {
+ cnt++;
+ }
+ }
+ return cnt;
+}
+// within the current dvert index, get the dw that is selected and has a weight above 0
+// this helps multi-paint
+static int get_first_selected_nonzero_weight(MDeformVert *dvert, char *selection) {
+ int i;
+ MDeformWeight *dw;
+ for(i=0; i< dvert->totweight; i++) {
+ dw = dvert->dw+i;
+ if(selection[dw->def_nr] && dw->weight > 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+// Jason
+static char *wpaint_make_validmap(Object *ob);
static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
float alpha, float paintweight, int flip,
- int vgroup_mirror, char *validmap)
+ int vgroup_mirror, char *validmap, int multipaint)
{
Mesh *me= ob->data;
- MDeformWeight *dw, *uw;
+ // Jason: tdw, tuw
+ MDeformWeight *dw, *uw, *tdw = NULL, *tuw;
int vgroup= ob->actdef-1;
-
+
+ /* Jason was here */
+ char *flags;
+ char *bone_groups;
+ char *selection;
+ int selected;
+ float oldw;
+ float neww;
+ float testw=0;
+ int defcnt;
+ float change = 0;
+ float oldChange = 0;
+ int i;
+ MDeformVert *dv = NULL;
+
+ // Need to know which groups are bone groups
+ if(validmap) {
+ bone_groups = validmap;
+ }else {
+ bone_groups = wpaint_make_validmap(ob);
+ }
+
if(wp->flag & VP_ONLYVGROUP) {
dw= defvert_find_index(me->dvert+index, vgroup);
uw= defvert_find_index(wp->wpaint_prev+index, vgroup);
@@ -1115,9 +1585,77 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
}
if(dw==NULL || uw==NULL)
return;
+ /* Jason was here */
+ flags = gen_lck_flags(ob, defcnt = BLI_countlist(&ob->defbase), bone_groups);
+ selection = get_selected_defgroups(ob, defcnt);
+ selected = count_true(selection, defcnt);
+ if(!selected && ob->actdef) {
+ selected = 1;
+ }
- wpaint_blend(wp, dw, uw, alpha, paintweight, flip);
- do_weight_paint_auto_normalize(me->dvert+index, vgroup, validmap);
+ oldw = dw->weight;
+ wpaint_blend(wp, dw, uw, alpha, paintweight, flip, multipaint && selected >1);
+ neww = dw->weight;
+ dw->weight = oldw;
+
+ // setup multi-paint
+ if(selected > 1 && multipaint) {
+ dv = MEM_mallocN(sizeof (*(me->dvert+index)), "prevMDeformVert");
+
+ dv->dw= MEM_dupallocN((me->dvert+index)->dw);
+ dv->flag = (me->dvert+index)->flag;
+ dv->totweight = (me->dvert+index)->totweight;
+ tdw = dw;
+ tuw = uw;
+ change = get_mp_change(wp->wpaint_prev+index, selection, neww-oldw);
+ if(change) {
+ if(!tdw->weight) {
+ i = get_first_selected_nonzero_weight(me->dvert+index, selection);
+ if(i>=0) {
+ tdw = ((me->dvert+index)->dw+i);
+ tuw = defvert_verify_index(wp->wpaint_prev+index, tdw->def_nr);
+ } else {
+ change = 0;
+ }
+ }
+ if(change && tuw->weight && tuw->weight * change) {
+ if(tdw->weight != tuw->weight) {
+ oldChange = tdw->weight/tuw->weight;
+ testw = tuw->weight*change;
+ if( testw > tuw->weight ) {
+ if(change > oldChange) {
+ // reset the weights and use the new change
+ reset_to_prev(wp->wpaint_prev+index, me->dvert+index);
+ } else {
+ // the old change was more significant,
+ // so set the change to 0 so that it will not do another multi-paint
+ change = 0;
+ }
+ } else {
+ if(change < oldChange) {
+ reset_to_prev(wp->wpaint_prev+index, me->dvert+index);
+ } else {
+ change = 0;
+ }
+ }
+ }
+ } else {
+ change = 0;
+ }
+ }
+ }
+ /* Jason was here */
+ if(apply_mp_lcks_normalize(ob, me, index, dw, tdw, defcnt, change, oldChange, oldw, neww, selection, selected, bone_groups, validmap, flags, multipaint)) {
+ reset_to_prev(dv, me->dvert+index);
+ change = 0;
+ oldChange = 0;
+ }
+ if(dv) {
+ MEM_freeN(dv->dw);
+ MEM_freeN(dv);
+ }
+ // dvert may have been altered greatly
+ dw = defvert_find_index(me->dvert+index, vgroup);
if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
int j= mesh_get_x_mirror_vert(ob, index);
@@ -1127,15 +1665,22 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
uw= defvert_verify_index(me->dvert+j, vgroup_mirror);
else
uw= defvert_verify_index(me->dvert+j, vgroup);
-
- uw->weight= dw->weight;
-
- do_weight_paint_auto_normalize(me->dvert+j, vgroup, validmap);
+ /* Jason */
+ //uw->weight= dw->weight;
+ /* Jason */
+ apply_mp_lcks_normalize(ob, me, j, uw, tdw, defcnt, change, oldChange, oldw, neww, selection, selected, bone_groups, validmap, flags, multipaint);
}
}
+ /* Jason */
+ if(flags) {
+ MEM_freeN(flags);
+ }
+ MEM_freeN(selection);
+ if(!validmap) {
+ MEM_freeN(bone_groups);
+ }
}
-
/* *************** set wpaint operator ****************** */
static int set_wpaint(bContext *C, wmOperator *UNUSED(op)) /* toggle */
@@ -1297,7 +1842,7 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED
struct WPaintData *wpd;
Mesh *me;
float mat[4][4], imat[4][4];
-
+
if(scene->obedit) return OPERATOR_CANCELLED;
me= get_mesh(ob);
@@ -1308,13 +1853,14 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED
ED_vgroup_data_create(&me->id);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
}
-
+
+
/* make mode data storage */
wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData");
paint_stroke_set_mode_data(stroke, wpd);
view3d_set_viewcontext(C, &wpd->vc);
wpd->vgroup_mirror= -1;
-
+
/*set up auto-normalize, and generate map for detecting which
vgroups affect deform bones*/
wpd->auto_normalize = ts->auto_normalize;
@@ -1369,7 +1915,7 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED
if(me->editflag & ME_EDIT_MIRROR_X) {
wpaint_mirror_vgroup_ensure(ob, &wpd->vgroup_mirror);
}
-
+
return 1;
}
@@ -1389,6 +1935,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
float alpha;
float mval[2], pressure;
+ // Jason
+ int selectedVerts;
+
/* cannot paint if there is no stroke data */
if (wpd == NULL) {
// XXX: force a redraw here, since even though we can't paint,
@@ -1436,6 +1985,8 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
}
}
}
+ // Jason
+ selectedVerts = (me->editflag & ME_EDIT_VERT_SEL);
if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
for(index=0; index<totindex; index++) {
@@ -1461,10 +2012,10 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if(indexar[index] && indexar[index]<=me->totface) {
MFace *mface= me->mface + (indexar[index]-1);
- (me->dvert+mface->v1)->flag= 1;
- (me->dvert+mface->v2)->flag= 1;
- (me->dvert+mface->v3)->flag= 1;
- if(mface->v4) (me->dvert+mface->v4)->flag= 1;
+ (me->dvert+mface->v1)->flag= selectedVerts ? ((me->mvert+mface->v1)->flag & SELECT): 1;
+ (me->dvert+mface->v2)->flag= selectedVerts ? ((me->mvert+mface->v2)->flag & SELECT): 1;
+ (me->dvert+mface->v3)->flag= selectedVerts ? ((me->mvert+mface->v3)->flag & SELECT): 1;
+ if(mface->v4) (me->dvert+mface->v4)->flag= selectedVerts ? ((me->mvert+mface->v4)->flag & SELECT): 1;
if(brush->vertexpaint_tool==VP_BLUR) {
MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
@@ -1501,7 +2052,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if(alpha) {
do_weight_paint_vertex(wp, ob, mface->v1,
alpha, paintweight, flip, wpd->vgroup_mirror,
- wpd->vgroup_validmap);
+ wpd->vgroup_validmap, ts->multipaint);
}
(me->dvert+mface->v1)->flag= 0;
}
@@ -1511,7 +2062,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if(alpha) {
do_weight_paint_vertex(wp, ob, mface->v2,
alpha, paintweight, flip, wpd->vgroup_mirror,
- wpd->vgroup_validmap);
+ wpd->vgroup_validmap, ts->multipaint);
}
(me->dvert+mface->v2)->flag= 0;
}
@@ -1521,7 +2072,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if(alpha) {
do_weight_paint_vertex(wp, ob, mface->v3,
alpha, paintweight, flip, wpd->vgroup_mirror,
- wpd->vgroup_validmap);
+ wpd->vgroup_validmap, ts->multipaint);
}
(me->dvert+mface->v3)->flag= 0;
}
@@ -1532,7 +2083,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
if(alpha) {
do_weight_paint_vertex(wp, ob, mface->v4,
alpha, paintweight, flip, wpd->vgroup_mirror,
- wpd->vgroup_validmap);
+ wpd->vgroup_validmap, ts->multipaint);
}
(me->dvert+mface->v4)->flag= 0;
}
@@ -1645,7 +2196,7 @@ void PAINT_OT_weight_set(wmOperatorType *ot)
/* api callbacks */
ot->exec= weight_paint_set_exec;
- ot->poll= facemask_paint_poll;
+ ot->poll= mask_paint_poll; // Jason, it was facemask_paint_poll
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -1787,14 +2338,15 @@ static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index
Brush *brush = paint_brush(&vp->paint);
Mesh *me = get_mesh(ob);
MFace *mface= ((MFace*)me->mface) + index;
+
unsigned int *mcol= ((unsigned int*)me->mcol) + 4*index;
unsigned int *mcolorig= ((unsigned int*)vp->vpaint_prev) + 4*index;
float alpha;
int i;
-
+
if((vp->flag & VP_COLINDEX && mface->mat_nr!=ob->actcol-1) ||
((me->editflag & ME_EDIT_PAINT_MASK) && !(mface->flag & ME_FACE_SEL)))
- return;
+ return;
if(brush->vertexpaint_tool==VP_BLUR) {
unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 71c85483244..86826ffc7e1 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -523,7 +523,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
if(ob->mode & OB_MODE_EDIT)
return;
else if(ob==OBACT)
- if(paint_facesel_test(ob))
+ if(paint_facesel_test(ob) || paint_vertsel_test(ob))
return;
ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index ddc10d78cac..a2abe1c4a29 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -1670,7 +1670,45 @@ void mesh_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, EditVe
dm->release(dm);
}
+/*Jason */
+static void mesh_obmode_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
+{
+ struct { void (*func)(void *userData, MVert *mv, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
+ Mesh *me = data->vc.obact->data;
+ MVert *mv = me->mvert+index;
+ //MVert *dmv = CDDM_get_verts(data->vc.obact->derivedFinal)+index;
+ //MVert *mv = CDDM_get_verts(data->vc.obact->derivedFinal)+index;
+ if ((mv->flag & ME_HIDE)==0) {
+ short s[2]= {IS_CLIPPED, 0};
+
+ if (data->clipVerts) {
+ view3d_project_short_clip(data->vc.ar, co, s, 1);
+ } else {
+ view3d_project_short_noclip(data->vc.ar, co, s);
+ }
+
+ if (s[0]!=IS_CLIPPED)
+ data->func(data->userData, mv, s[0], s[1], index);
+ }
+}
+/*Jason*/
+void mesh_obmode_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, MVert *mv, int x, int y, int index), void *userData, int clipVerts)
+{
+ struct { void (*func)(void *userData, MVert *mv, int x, int y, int index); void *userData; ViewContext vc; int clipVerts; } data;
+ DerivedMesh *dm = mesh_get_derived_final(vc->scene, vc->obact, CD_MASK_BAREMESH);
+
+ data.vc= *vc;
+ data.func = func;
+ data.userData = userData;
+ data.clipVerts = clipVerts;
+
+ if(clipVerts)
+ ED_view3d_local_clipping(vc->rv3d, vc->obact->obmat); /* for local clipping lookups */
+
+ dm->foreachMappedVert(dm, mesh_obmode_foreachScreenVert__mapFunc, &data);
+ dm->release(dm);
+}
static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
{
struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ViewContext vc; int clipVerts; } *data = userData;
@@ -2774,7 +2812,6 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
}
}
-
/* set default draw color back for wire or for draw-extra later on */
if (dt!=OB_WIRE) {
if(base->flag & SELECT) {
@@ -2833,7 +2870,13 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
bglPolygonOffset(rv3d->dist, 0.0);
}
}
-
+ // Jason
+ if(paint_vertsel_test(ob) && dm->drawSelectedVerts) {
+ glColor3f(0.0f, 0.0f, 0.0f);
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+ dm->drawSelectedVerts(dm);
+ glPointSize(1.0f);
+ }
dm->release(dm);
}
@@ -6383,6 +6426,29 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
}
/* ***************** BACKBUF SEL (BBS) ********* */
+/* Jason */
+static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
+{
+ // TODO: support hidden vertices
+ int offset = (intptr_t) userData;
+ //EditVert *eve = EM_get_vert_for_index(index);
+
+ //if (eve->h==0) {
+ WM_set_framebuffer_index_color(offset+index);
+ bglVertex3fv(co);
+ //}
+}
+/* Jason */
+static void bbs_obmode_mesh_verts(Scene* scene, Object *ob, DerivedMesh *dm, int offset)
+{
+ Mesh *me = (Mesh*)ob->data;
+
+ glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
+ bglBegin(GL_POINTS);
+ dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, (void*)(intptr_t) offset);
+ bglEnd();
+ glPointSize(1.0);
+}
static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
{
@@ -6481,7 +6547,18 @@ static int bbs_mesh_solid_hide__setDrawOpts(void *userData, int index, int *UNUS
return 0;
}
}
+/* Jason */
+// must have called WM_set_framebuffer_index_color beforehand
+static int bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index, int *UNUSED(drawSmooth_r))
+{
+ Mesh *me = userData;
+ if (!(me->mface[index].flag&ME_HIDE)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
static void bbs_mesh_solid(Scene *scene, Object *ob)
{
DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
@@ -6540,7 +6617,23 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
EM_free_index_arrays();
}
- else bbs_mesh_solid(scene, ob);
+ else {
+ Mesh *me= ob->data;
+ if(me->editflag & ME_EDIT_VERT_SEL) {
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
+ WM_set_framebuffer_index_color(me->totvert+2);
+ glColor3ub(0, 0, 0);
+
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, me, 0, GPU_enable_material);
+
+
+ bbs_obmode_mesh_verts(scene, ob, dm, 1);
+ em_vertoffs = me->totvert+1;
+ dm->release(dm);
+ }
+ else bbs_mesh_solid(scene, ob);
+ }
+
}
break;
case OB_CURVE:
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 6833dec2e43..8773a67447f 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -371,6 +371,10 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
keymap= WM_keymap_find(wm->defaultconf, "Face Mask", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
+ /* Jason */
+ keymap= WM_keymap_find(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
/* pose is not modal, operator poll checks for this */
keymap= WM_keymap_find(wm->defaultconf, "Pose", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 78dcf6c9a5c..b29373d0770 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -498,9 +498,15 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
/* Manipulators aren't used in weight paint mode */
PointerRNA meshptr;
-
RNA_pointer_create(&ob->id, &RNA_Mesh, ob->data, &meshptr);
- uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ if(ob->mode & (OB_MODE_TEXTURE_PAINT|OB_MODE_VERTEX_PAINT)) {
+ uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ } else {
+ // Jason
+ row= uiLayoutRow(layout, 1);
+ uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ uiItemR(row, &meshptr, "wp_vert_sel", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ }
} else {
const char *str_menu;
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 86112a42d99..fb69df258b5 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -54,6 +54,11 @@
#include "BLI_linklist.h"
#include "BLI_utildefines.h"
+// Jason--vertex box select
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "BKE_global.h"
+
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_armature.h"
@@ -197,6 +202,22 @@ static void EM_backbuf_checkAndSelectFaces(EditMesh *em, int select)
}
}
}
+/* Jason */
+static void EM_backbuf_checkAndSelectTVerts(Mesh *me, int select)
+{
+ MVert *mv = me->mvert;
+ int a;
+
+ if (mv) {
+ for(a=1; a<=me->totvert; a++, mv++) {
+ if(EM_check_backbuf(a)) {
+ if(!(mv->flag & ME_HIDE)) {
+ mv->flag = select?(mv->flag|SELECT):(mv->flag&~SELECT);
+ }
+ }
+ }
+ }
+}
static void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
{
@@ -231,7 +252,7 @@ static int view3d_selectable_data(bContext *C)
if (ob->mode & OB_MODE_SCULPT) {
return 0;
}
- if (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT) && !paint_facesel_test(ob)) {
+ if (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT) && !paint_facesel_test(ob) && !paint_vertsel_test(ob)) {//Jason
return 0;
}
}
@@ -625,7 +646,6 @@ static void do_lasso_select_curve(ViewContext *vc, int mcords[][2], short moves,
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data);
}
-
static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x, int y)
{
struct { int (*mcords)[2]; short moves; short select; } *data = userData;
@@ -726,7 +746,89 @@ static void do_lasso_select_meta(ViewContext *vc, int mcords[][2], short moves,
}
}
}
+/* Jason */
+int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+{
+ Mesh *me;
+ MVert *mvert;
+ struct ImBuf *ibuf;
+ unsigned int *rt;
+ int a, index;
+ char *selar;
+ int sx= rect->xmax-rect->xmin+1;
+ int sy= rect->ymax-rect->ymin+1;
+
+ me= vc->obact->data;
+
+ if(me==NULL || me->totvert==0 || sx*sy <= 0)
+ return OPERATOR_CANCELLED;
+
+ selar= MEM_callocN(me->totvert+1, "selar");
+
+ if (extend == 0 && select)
+ paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
+
+ view3d_validate_backbuf(vc);
+
+ ibuf = IMB_allocImBuf(sx,sy,32,IB_rect);
+ rt = ibuf->rect;
+ glReadPixels(rect->xmin+vc->ar->winrct.xmin, rect->ymin+vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
+
+ a= sx*sy;
+ while(a--) {
+ if(*rt) {
+ index= WM_framebuffer_to_index(*rt);
+ if(index<=me->totvert) selar[index]= 1;
+ }
+ rt++;
+ }
+
+ mvert= me->mvert;
+ for(a=1; a<=me->totvert; a++, mvert++) {
+ if(selar[a]) {
+ if(mvert->flag & ME_HIDE);
+ else {
+ if(select) mvert->flag |= SELECT;
+ else mvert->flag &= ~SELECT;
+ }
+ }
+ }
+
+ IMB_freeImBuf(ibuf);
+ MEM_freeN(selar);
+
+#ifdef __APPLE__
+ glReadBuffer(GL_BACK);
+#endif
+
+ paintvert_flush_flags(vc->obact);
+
+ return OPERATOR_FINISHED;
+}
+/* Jason */
+static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
+{
+ Object *ob= vc->obact;
+ Mesh *me= ob?ob->data:NULL;
+ rcti rect;
+
+ if(me==NULL || me->totvert==0)
+ return;
+
+ if(extend==0 && select)
+ paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
+ em_vertoffs= me->totvert+1; /* max index array */
+
+ lasso_select_boundbox(&rect, mcords, moves);
+ EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ EM_backbuf_checkAndSelectTVerts(me, select);
+
+ EM_free_backbuf();
+
+ paintvert_flush_flags(ob);
+}
static void do_lasso_select_paintface(ViewContext *vc, int mcords[][2], short moves, short extend, short select)
{
Object *ob= vc->obact;
@@ -789,6 +891,8 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc, int mcords[][2], s
if(vc->obedit==NULL) { /* Object Mode */
if(paint_facesel_test(ob))
do_lasso_select_paintface(vc, mcords, moves, extend, select);
+ else if(paint_vertsel_test(ob))
+ do_lasso_select_paintvert(vc, mcords, moves, extend, select);
else if(ob && ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))
;
else if(ob && ob->mode & OB_MODE_PARTICLE_EDIT)
@@ -1792,6 +1896,9 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
else if(vc.obact && paint_facesel_test(vc.obact)) {
ret= do_paintface_box_select(&vc, &rect, select, extend);
}
+ else if(vc.obact && paint_vertsel_test(vc.obact)) {
+ ret= do_paintvert_box_select(&vc, &rect, select, extend);
+ }
else if(vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
ret= PE_border_select(C, &rect, select, extend);
}
@@ -1827,6 +1934,57 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
/* rna */
WM_operator_properties_gesture_border(ot, TRUE);
}
+/*Jason*/
+/* much like facesel_face_pick()*/
+/* returns 0 if not found, otherwise 1 */
+static int vertsel_vert_pick(struct bContext *C, Mesh *me, const int mval[2], unsigned int *index, short rect)
+{
+ ViewContext vc;
+ view3d_set_viewcontext(C, &vc);
+
+ if (!me || me->totvert==0)
+ return 0;
+
+ if (rect) {
+ /* sample rect to increase changes of selecting, so that when clicking
+ on an face in the backbuf, we can still select a vert */
+
+ int dist;
+ *index = view3d_sample_backbuf_rect(&vc, mval, 3, 1, me->totvert+1, &dist,0,NULL, NULL);
+ }
+ else {
+ /* sample only on the exact position */
+ *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+ }
+
+ if ((*index)<=0 || (*index)>(unsigned int)me->totvert)
+ return 0;
+
+ (*index)--;
+
+ return 1;
+}
+/* Jason */
+/* mouse selection in weight paint */
+/* gets called via generic mouse select operator */
+int mouse_wp_select(bContext *C, const int mval[2], short extend, Object *obact, Mesh* me)
+{
+ unsigned int index = 0;
+ MVert *mv;
+ if(vertsel_vert_pick(C, me, mval, &index, 1)) {
+ mv = me->mvert+index;
+ if(extend) {
+ mv->flag ^= 1;
+ } else {
+ paintvert_deselect_all_visible(obact, SEL_DESELECT, FALSE);
+ mv->flag |= 1;
+ }
+ paintvert_flush_flags(obact);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obact->data);
+ return 1;
+ }
+ return 0;
+}
/* ****** Mouse Select ****** */
@@ -1839,6 +1997,9 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
short center= RNA_boolean_get(op->ptr, "center");
short enumerate= RNA_boolean_get(op->ptr, "enumerate");
int retval = 0;
+ // Jason
+ Mesh *me;
+ Scene *scene = CTX_data_scene(C);
view3d_operator_needs_opengl(C);
@@ -1861,8 +2022,12 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
return PE_mouse_particles(C, event->mval, extend);
else if(obact && paint_facesel_test(obact))
retval = paintface_mouse_select(C, obact, event->mval, extend);
- else
+ /*Jason*/
+ else if (paint_vertsel_test(obact) && (me = (Mesh*)(obact->data))) {
+ retval = mouse_wp_select(C, event->mval, extend, obact, me);
+ } else {
retval = mouse_select(C, event->mval, extend, center, enumerate);
+ }
/* passthrough allows tweaks
* FINISHED to signal one operator worked
@@ -1906,6 +2071,7 @@ static void mesh_circle_doSelectVert(void *userData, EditVert *eve, int x, int y
eve->f = data->select?(eve->f|1):(eve->f&~1);
}
}
+
static void mesh_circle_doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
{
struct {ViewContext *vc; short select; int mval[2]; float radius; } *data = userData;
@@ -1985,6 +2151,24 @@ static void paint_facesel_circle_select(ViewContext *vc, int select, const int m
}
}
+/* Jason */
+static void paint_vertsel_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
+{
+ Object *ob= vc->obact;
+ Mesh *me = ob?ob->data:NULL;
+ int bbsel;
+ struct {ViewContext *vc; short select; int mval[2]; float radius; } data = {NULL};
+ if (me) {
+ em_vertoffs= me->totvert+1; /* max index array */
+
+ bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
+ EM_backbuf_checkAndSelectTVerts(me, select==LEFTMOUSE);
+ EM_free_backbuf();
+
+ paintvert_flush_flags(ob);
+ }
+}
+
static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
{
@@ -2239,8 +2423,8 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
int select;
select= (gesture_mode==GESTURE_MODAL_SELECT);
-
- if( CTX_data_edit_object(C) || paint_facesel_test(obact) ||
+ // Jason
+ if( CTX_data_edit_object(C) || paint_facesel_test(obact) || paint_vertsel_test(obact) ||
(obact && (obact->mode & (OB_MODE_PARTICLE_EDIT|OB_MODE_POSE))) )
{
ViewContext vc;
@@ -2259,6 +2443,10 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
else if(paint_facesel_test(obact)) {
paint_facesel_circle_select(&vc, select, mval, (float)radius);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obact->data);
+ }/* Jason */
+ else if(paint_vertsel_test(obact)) {
+ paint_vertsel_circle_select(&vc, select, mval, (float)radius);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obact->data);
}
else if(obact->mode & OB_MODE_POSE)
pose_circle_select(&vc, select, mval, (float)radius);
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 6ad60ac2df9..bbd21a89f0a 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -125,7 +125,7 @@ typedef struct TFace {
#define ME_EDIT_PAINT_MASK (1 << 3)
#define ME_EDIT_MIRROR_TOPO (1 << 4)
-
+#define ME_EDIT_VERT_SEL (1 << 5)// Jason
/* me->flag */
/* #define ME_ISDONE 1 */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index dfc7d42793d..b1b3e779824 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -62,6 +62,8 @@ struct bGPdata;
typedef struct bDeformGroup {
struct bDeformGroup *next, *prev;
char name[32];
+ /* Jason was here: need this flag for locking weights */
+ char flag, pad[7];
} bDeformGroup;
#define MAX_VGROUP_NAME 32
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 2211f93a8ae..dcf646532c4 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -726,10 +726,13 @@ typedef struct ToolSettings {
short snap_flag, snap_target;
short proportional, prop_mode;
char proportional_objects; /* proportional edit, object mode */
- char pad[3];
+ char pad[7];
int auto_normalize; /*auto normalizing mode in wpaint*/
+ //Jason
+ int multipaint; /* paint multiple bones in wpaint */
+
short sculpt_paint_settings; /* user preferences for sculpt and paint */
short pad1;
int sculpt_paint_unified_size; /* unified radius of brush in pixels */
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index c0ae7b02b1a..14262184988 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -214,6 +214,8 @@ int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current);
void rna_Object_internal_update_data(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
void rna_Mesh_update_draw(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
void rna_TextureSlot_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
+//Jason
+void rna_update_active_object(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
/* basic poll functions for object types */
int rna_Armature_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 80c98e8c428..a8b191c0576 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -90,6 +90,24 @@ void rna_Mesh_update_draw(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA
}
}
+/* Jason */
+void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Mesh* me = ptr->data;
+ if ((me->editflag & ME_EDIT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_MASK)) {
+ me->editflag ^= ME_EDIT_PAINT_MASK;
+ }
+ rna_Mesh_update_draw(bmain, scene, ptr);
+}
+/* Jason */
+void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Mesh* me = ptr->data;
+ if ((me->editflag & ME_EDIT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_MASK)) {
+ me->editflag ^= ME_EDIT_VERT_SEL;
+ }
+ rna_Mesh_update_draw(bmain, scene, ptr);
+}
static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value)
{
MVert *mvert= (MVert*)ptr->data;
@@ -2075,8 +2093,14 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_PAINT_MASK);
RNA_def_property_ui_text(prop, "Paint Mask", "Face selection masking for painting");
RNA_def_property_ui_icon(prop, ICON_FACESEL_HLT, 0);
- RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
-
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_facemask");
+
+ /* Jason */
+ prop= RNA_def_property(srna, "wp_vert_sel", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_VERT_SEL);
+ RNA_def_property_ui_text(prop, "Vertex Selection", "Vertex selection masking for painting");
+ RNA_def_property_ui_icon(prop, ICON_VERTEXSEL, 0);
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_vertmask");
/* readonly editmesh info - use for extrude menu */
prop= RNA_def_property(srna, "total_vert_sel", PROP_INT, PROP_UNSIGNED);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 55e1119f58e..d7440ad9ddb 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -218,6 +218,16 @@ void rna_Object_internal_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene),
DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT|ND_DRAW, ptr->id.data);
}
+// Jason
+void rna_update_active_object(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ Object *ob;
+ Base *basact = scene->basact;
+ if(basact && (ob = basact->object)) {
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT|ND_DRAW, &ob->id);
+ }
+}
void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
@@ -1256,6 +1266,11 @@ static void rna_def_vertex_group(BlenderRNA *brna)
RNA_def_struct_name_property(srna, prop);
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_VertexGroup_name_set");
RNA_def_property_update(prop, NC_GEOM|ND_DATA|NA_RENAME, "rna_Object_internal_update_data"); /* update data because modifiers may use [#24761] */
+ /* Jason was here */
+ prop= RNA_def_property(srna, "flag", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "", "Maintain the relative weights for the group");
+ RNA_def_property_boolean_sdna(prop, "bDeformGroup", "flag", 0);
+ RNA_def_property_update(prop, NC_GEOM|ND_DATA|NA_RENAME, "rna_Object_internal_update_data"); /* update data because modifiers may use [#24761] */
prop= RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 29cfc695911..5d191b07059 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1090,6 +1090,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "WPaint Auto-Normalize",
"Ensure all bone-deforming vertex groups add up to 1.0 while "
"weight painting");
+ RNA_def_property_update(prop, 0, "rna_update_active_object");
+
+ prop = RNA_def_property(srna, "use_multipaint", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "multipaint", 1);
+ RNA_def_property_ui_text(prop, "WPaint Multi-Paint",
+ "Paint across all selected bones while "
+ "weight painting");
+ RNA_def_property_update(prop, 0, "rna_update_active_object");
prop= RNA_def_property(srna, "vertex_paint", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "vpaint");