diff options
35 files changed, 1967 insertions, 94 deletions
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake index f09a8058f14..d2b791baede 100644 --- a/build_files/cmake/config/blender_lite.cmake +++ b/build_files/cmake/config/blender_lite.cmake @@ -1,4 +1,4 @@ -# turn everything OFF except for python which defaults to ON +# turn everything OFF CACHE FORCE BOOL) except for python which defaults to ON # and is needed for the UI # # Example usage: diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 75df7dad5f2..7503959480b 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -135,7 +135,8 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel): ob = context.object group = ob.vertex_groups.active - + + rows = 2 if group: rows = 5 @@ -144,6 +145,9 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel): row.template_list(ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows) col = row.column(align=True) + # Jason was here, this was replaced by hardcoded list view checkboxes. # + #col.prop(group, "flag") + col.operator("object.vertex_group_add", icon='ZOOMIN', text="") col.operator("object.vertex_group_remove", icon='ZOOMOUT', text="") col.menu("MESH_MT_vertex_group_specials", icon='DOWNARROW_HLT', text="") @@ -154,6 +158,14 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel): if group: row = layout.row() row.prop(group, "name") + #Jason was here + # add buttons to make it faster to lock/unlock vgroups + if ob.mode == 'WEIGHT_PAINT' and len(ob.vertex_groups) > 0: + row = layout.row() + sub = row.row(align=True) + sub.operator("object.vertex_group_lock_all", text="Lock All") + sub.operator("object.vertex_group_invert_locks", text="Invert Locks") + sub.operator("object.vertex_group_unlock_all", text="Unlock All") if ob.mode == 'EDIT' and len(ob.vertex_groups) > 0: row = layout.row() diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 9f96df1eb66..c9817cdf905 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1072,6 +1072,8 @@ class VIEW3D_MT_paint_weight(Menu): layout.operator("object.vertex_group_invert", text="Invert") layout.operator("object.vertex_group_clean", text="Clean") layout.operator("object.vertex_group_levels", text="Levels") + #Jason + layout.operator("object.vertex_group_fix", text="Fix Deforms") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index b71593add96..23d896abdbb 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -643,6 +643,8 @@ class VIEW3D_PT_tools_brush(PaintPanel, Panel): elif context.weight_paint_object and brush: layout.prop(context.tool_settings, "vertex_group_weight", text="Weight", slider=True) layout.prop(context.tool_settings, "use_auto_normalize", text="Auto Normalize") + # Jason was here + layout.prop(context.tool_settings, "use_multipaint", text="Multi-Paint") col = layout.column() @@ -1055,6 +1057,7 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel): col.operator("object.vertex_group_invert", text="Invert") col.operator("object.vertex_group_clean", text="Clean") col.operator("object.vertex_group_levels", text="Levels") + col.operator("object.vertex_group_fix", text="Fix Deforms") class VIEW3D_PT_tools_weightpaint_options(View3DPanel, Panel): diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 6e17b056685..a109d5722ab 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 ff7f2586767..4b6d51dfbda 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" /////////////////////////////////// /////////////////////////////////// @@ -1607,19 +1612,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); @@ -1638,26 +1674,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); } @@ -1864,7 +1943,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. @@ -1976,7 +2055,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 { @@ -1988,7 +2067,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 */ @@ -2261,7 +2340,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 5eb97630e83..0dde94bc639 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) { @@ -1554,6 +1592,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 eaaaa12eca1..960ab318dab 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -4276,28 +4276,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); } @@ -5061,6 +5102,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; @@ -5090,7 +5135,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 f8682d3935b..648d9cf4a84 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/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 c308d36f838..0a4c6b638a3 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -200,6 +200,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 8f00f923b84..3e8c34b7395 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -174,6 +174,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 d69c1d9c447..226c71b0573 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 6e02ecbd5a8..b8d33de2e37 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 d573198aa10..459a07d03a4 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1712,7 +1712,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; @@ -2897,7 +2935,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); } @@ -6462,6 +6506,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)) { @@ -6560,7 +6627,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); @@ -6619,7 +6697,22 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec EM_free_index_arrays(); } else { - bbs_mesh_solid(scene, ob); + 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, NULL); + + + 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 65914ead899..926678ab123 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) @@ -1798,6 +1902,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); } @@ -1833,6 +1940,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 ****** */ @@ -1846,6 +2004,9 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event) short enumerate= RNA_boolean_get(op->ptr, "enumerate"); short object= RNA_boolean_get(op->ptr, "object"); int retval = 0; + // Jason + Mesh *me; + Scene *scene = CTX_data_scene(C); view3d_operator_needs_opengl(C); @@ -1878,8 +2039,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 @@ -1924,6 +2089,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; @@ -2003,6 +2169,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) { @@ -2257,8 +2441,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; @@ -2277,6 +2461,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 ffa82092ef1..820b244ca6c 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 be2a78ac774..bc50c710d76 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -732,10 +732,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 9e98f166875..cd395a4bbd8 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -215,6 +215,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 ad323b0aba4..f043249d36c 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -219,6 +219,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) { @@ -1258,6 +1268,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 cc1e7d9390b..1c5fe02e1f1 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1120,6 +1120,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"); |