diff options
author | Ton Roosendaal <ton@blender.org> | 2009-01-10 17:19:14 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2009-01-10 17:19:14 +0300 |
commit | dd97c080062bfa01883f6d6e9f2f6c0b8a0ba8c1 (patch) | |
tree | 6ffe875d47aafc0a8d7dea9c45e94ee25f35589a | |
parent | a7932f745243e5cb0192ec6bbef58dcea34faf0f (diff) |
2.5
- Weightpaint back (CTRL+TAB or menu)
Also weightpaint is sortof non-modal, allowing to use all existing
hotkeys while in paint mode. Only leftmouse is overridden.
- Made vpaint and wpaint entirely local, stored in scene (and saved!)
- Small bugfix (also in 2.48): on weightpaint mode, all armature objects
in 3d window were drawing as active poses. Now only the armature
deformer is.
Nice point for the UI agenda: are paint modes on ACTION mouse? Only then
you can combine it with SELECT mouse...
22 files changed, 530 insertions, 361 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d160c75a03b..063a0e4a31f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2054,15 +2054,16 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) { Mesh *me = ob->data; float min[3], max[3]; - int needMapping= 0; // + //int needMapping= 0; + + Object *obact = scene->basact?scene->basact->object:NULL; + int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT); + int needMapping = editing && (ob==obact); clear_mesh_caches(ob); -// XXX Object *obact = scene->basact?scene->basact->object:NULL; -// int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT); -// int needMapping = editing && (ob==obact); -// if( (G.f & G_WEIGHTPAINT) && ob==obact ) { - if(dataMask & CD_MASK_WEIGHTPAINT) { + if( (G.f & G_WEIGHTPAINT) && ob==obact ) { +// if(dataMask & CD_MASK_WEIGHTPAINT) { MCol *wpcol = (MCol*)calc_weightpaint_colors(ob); int layernum = CustomData_number_of_layers(&me->fdata, CD_MCOL); int prevactive = CustomData_get_active_layer(&me->fdata, CD_MCOL); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 91783a3c85f..3fc1d2a6103 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -167,7 +167,12 @@ void free_scene(Scene *sce) BLI_freelistN(&sce->transform_spaces); BLI_freelistN(&sce->r.layers); - if(sce->toolsettings){ + if(sce->toolsettings) { + if(sce->toolsettings->vpaint) + MEM_freeN(sce->toolsettings->vpaint); + if(sce->toolsettings->wpaint) + MEM_freeN(sce->toolsettings->wpaint); + MEM_freeN(sce->toolsettings); sce->toolsettings = NULL; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ac0b819aa6b..8c979a68d9a 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3604,7 +3604,10 @@ static void direct_link_scene(FileData *fd, Scene *sce) sce->radio= newdataadr(fd, sce->radio); sce->toolsettings= newdataadr(fd, sce->toolsettings); - + if(sce->toolsettings) { + sce->toolsettings->vpaint= newdataadr(fd, sce->toolsettings->vpaint); + sce->toolsettings->wpaint= newdataadr(fd, sce->toolsettings->wpaint); + } sce->sculptdata.session= NULL; /* SculptData textures */ for(a=0; a<MAX_MTEX; ++a) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 57dde906fa3..436980ef421 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1472,6 +1472,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase) writestruct(wd, DATA, "Radio", 1, sce->radio); writestruct(wd, DATA, "ToolSettings", 1, sce->toolsettings); + if(sce->toolsettings->vpaint) + writestruct(wd, DATA, "VPaint", 1, sce->toolsettings->vpaint); + if(sce->toolsettings->wpaint) + writestruct(wd, DATA, "VPaint", 1, sce->toolsettings->wpaint); for(a=0; a<MAX_MTEX; ++a) writestruct(wd, DATA, "MTex", 1, sce->sculptdata.mtex[a]); diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index eaf4ef7ae12..07816228dad 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -89,6 +89,15 @@ void ED_anim_dag_flush_update(const bContext *C) DAG_scene_flush_update(scene, screen_view3d_layers(screen), 0); } +/* flushes changes from object to all relations in scene */ +void ED_anim_object_flush_update(const bContext *C, Object *ob) +{ + Scene *scene= CTX_data_scene(C); + bScreen *screen= CTX_wm_screen(C); + + DAG_object_update_flags(scene, ob, screen_view3d_layers(screen)); +} + /* results in fully updated anim system */ /* in future sound should be on WM level, only 1 sound can play! */ diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 06855d4446d..99f89d84328 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -99,10 +99,7 @@ static void error_libdata() {} static void BIF_undo_push() {} static void adduplicate() {} static void countall() {} -static void vertexgroup_select_by_name() {} static void deselect_actionchannels() {} -static void add_vert_to_defgroup() {} -static void create_dverts() {} static void select_actionchannel_by_name() {} /* ************* XXX *************** */ @@ -3563,7 +3560,7 @@ static int bone_looper(Object *ob, Bone *bone, void *data, } /* called from editview.c, for mode-less pose selection */ -/* assumes scene obact and basact... XXX */ +/* 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; @@ -3605,8 +3602,8 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor /* in weightpaint we select the associated vertex group too */ if (G.f & G_WEIGHTPAINT) { if (nearBone->flag & BONE_ACTIVE) { - vertexgroup_select_by_name(ob, nearBone->name); - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + vertexgroup_select_by_name(OBACT, nearBone->name); + DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA); } } diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 807339b08e0..8807b21e653 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -58,20 +58,17 @@ #include "BLO_sys_types.h" // for intptr_t support +#include "ED_armature.h" +#include "ED_mesh.h" + #include "meshlaplacian.h" /* ************* XXX *************** */ -static void remove_vert_defgroup() {} -static int mesh_get_x_mirror_vert() {return 0;} static void waitcursor() {} static void progress_bar() {} static void start_progress_bar() {} static void end_progress_bar() {} -static float get_vert_defgroup() {return 0.0;} -static void add_vert_to_defgroup() {} -#define WEIGHT_REPLACE 0 -#define WEIGHT_ADD 0 static void error() {} /* ************* XXX *************** */ diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 94e5492a337..08a670b9582 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -52,6 +52,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_blender.h" +#include "BKE_context.h" #include "BKE_constraint.h" #include "BKE_deform.h" #include "BKE_depsgraph.h" @@ -66,8 +67,10 @@ #include "BIF_gl.h" #include "ED_armature.h" +#include "ED_anim_api.h" #include "ED_keyframing.h" #include "ED_object.h" +#include "ED_mesh.h" #include "ED_view3d.h" #include "armature_intern.h" @@ -81,8 +84,6 @@ static void error() {}; static void BIF_undo_push() {} static void countall() {} static void add_constraint() {} -static void vertexgroup_select_by_name() {} -static int screen_view3d_layers() {return 0;} static void select_actionchannel_by_name() {} static int autokeyframe_cfra_can_key() {return 0;} static void autokeyframe_pose_cb_func() {} @@ -194,7 +195,7 @@ int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan) /* For the object with pose/action: create path curves for selected bones * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range */ -void pose_calculate_path(Scene *scene, Object *ob) +void pose_calculate_path(bContext *C, Scene *scene, Object *ob) { bArmature *arm; bPoseChannel *pchan; @@ -230,10 +231,10 @@ void pose_calculate_path(Scene *scene, Object *ob) /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */ if ((ob->recalc & OB_RECALC)==0) { ob->recalc |= OB_RECALC; - DAG_object_update_flags(scene, ob, screen_view3d_layers()); + ED_anim_object_flush_update(C, ob); } else - DAG_object_update_flags(scene, ob, screen_view3d_layers()); + ED_anim_object_flush_update(C, ob); /* malloc the path blocks */ @@ -288,7 +289,7 @@ void pose_calculate_path(Scene *scene, Object *ob) /* For the object with pose/action: update paths for those that have got them * This should selectively update paths that exist... */ -void pose_recalculate_paths(Scene *scene, Object *ob) +void pose_recalculate_paths(bContext *C, Scene *scene, Object *ob) { bArmature *arm; bPoseChannel *pchan; @@ -324,10 +325,10 @@ void pose_recalculate_paths(Scene *scene, Object *ob) /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */ if ((ob->recalc & OB_RECALC)==0) { ob->recalc |= OB_RECALC; - DAG_object_update_flags(scene, ob, screen_view3d_layers()); + ED_anim_object_flush_update(C, ob); } else - DAG_object_update_flags(scene, ob, screen_view3d_layers()); + ED_anim_object_flush_update(C, ob); for (CFRA=sfra; CFRA<=efra; CFRA++) { /* do all updates */ @@ -1628,7 +1629,7 @@ void pose_special_editmenu(Scene *scene) pose_flip_names(); } else if(nr==3) { - pose_calculate_path(ob); + pose_calculate_path(C, ob); } else if(nr==4) { pose_clear_paths(ob); diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 863446fe59f..8b3d5df61ba 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -30,6 +30,7 @@ #define ED_ANIM_API_H struct ID; +struct Scene; struct ListBase; struct bContext; struct wmWindowManager; @@ -321,8 +322,11 @@ void ANIM_nla_mapping_apply_ipo(struct Object *ob, struct Ipo *ipo, short restor /* --------- anim_deps.c, animation updates -------- */ -/* generic update flush, reads from Context screen (layers) and scene */ + /* generic update flush, reads from Context screen (layers) and scene */ void ED_anim_dag_flush_update(const struct bContext *C); + /* only flush object */ +void ED_anim_object_flush_update(const struct bContext *C, struct Object *ob); + /* flush + do the actual update for all involved objects */ void ED_update_for_newframe(const struct bContext *C, int mute); /* pose <-> action syncing */ diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 17d6b25b93b..09b7f864f3e 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -91,7 +91,7 @@ void ED_armature_edit_remake(struct Object *obedit); int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short extend); void mouse_armature(struct bContext *C, short mval[2], int extend); - +struct Bone *get_indexed_bone (struct Object *ob, int index); float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3]); void transform_armature_mirror_update(struct Object *obedit); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 02419b9aca9..db97665a571 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -28,6 +28,7 @@ #ifndef ED_MESH_H #define ED_MESH_H +struct ID; struct View3D; struct ARegion; struct EditMesh; @@ -130,12 +131,17 @@ int EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short r #define WEIGHT_SUBTRACT 3 void add_defgroup (Object *ob); -void remove_vert_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum); +void create_dverts(struct ID *id); +float get_vert_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum); +void remove_vert_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum); void remove_verts_defgroup (Object *obedit, int allverts); -struct bDeformGroup *add_defgroup_name (Object *ob, char *name); -struct MDeformWeight *verify_defweight (struct MDeformVert *dv, int defgroup); -struct MDeformWeight *get_defweight (struct MDeformVert *dv, int defgroup); -bDeformGroup *add_defgroup_name (Object *ob, char *name); +void vertexgroup_select_by_name(Object *ob, char *name); +void add_vert_to_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum, + float weight, int assignmode); + +struct bDeformGroup *add_defgroup_name (Object *ob, char *name); +struct MDeformWeight *verify_defweight (struct MDeformVert *dv, int defgroup); +struct MDeformWeight *get_defweight (struct MDeformVert *dv, int defgroup); #endif /* ED_MESH_H */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 60a5ff8481e..4f4afd2abb4 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -53,29 +53,6 @@ typedef struct ViewContext { short mval[2]; } ViewContext; -typedef struct VPaint { - float r, g, b, a; - float size; /* of brush */ - float gamma, mul; - short mode, flag; - int tot, pad; /* allocation size of prev buffers */ - unsigned int *vpaint_prev; /* previous mesh colors */ - struct MDeformVert *wpaint_prev; /* previous vertex weights */ - - void *paintcursor; /* wm handle */ -} VPaint; - -/* Gvp.flag and Gwp.flag */ -#define VP_COLINDEX 1 -#define VP_AREA 2 -#define VP_SOFT 4 -#define VP_NORMALS 8 -#define VP_SPRAY 16 -#define VP_MIRROR_X 32 -#define VP_HARD 64 -#define VP_ONLYVGROUP 128 - - float *give_cursor(struct Scene *scene, struct View3D *v3d); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 1c95103bcc9..4f5426b44ef 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -725,7 +725,7 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode) * we are using the undeformed coordinates*/ INIT_MINMAX(min, max); - if(me->edit_mesh==em) { + if(em && me->edit_mesh==em) { EditVert *eve; for(eve= em->verts.first; eve; eve= eve->next) @@ -766,7 +766,7 @@ intptr_t mesh_octree_table(Object *ob, EditMesh *em, float *co, char mode) MeshOctree.table= MEM_callocN(MOC_RES*MOC_RES*MOC_RES*sizeof(void *), "sym table"); - if(me->edit_mesh==em) { + if(em && me->edit_mesh==em) { EditVert *eve; for(eve= em->verts.first; eve; eve= eve->next) { diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index e3fa8b22463..c6cbbf90b79 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1629,7 +1629,6 @@ void OBJECT_OT_set_restrictview(wmOperatorType *ot) /* ************* Slow Parent ******************* */ static int object_set_slowparent_exec(bContext *C, wmOperator *op) { - Scene *scene= CTX_data_scene(C); CTX_DATA_BEGIN(C, Base*, base, visible_bases) { diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 6f341c6a6fe..9fa045830ab 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -62,6 +62,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_ipo.h" #include "BKE_utildefines.h" @@ -2542,9 +2543,10 @@ int draw_armature(Scene *scene, View3D *v3d, Base *base, int dt, int flag) if ((flag & DRAW_SCENESET)==0) { if(ob==OBACT) arm->flag |= ARM_POSEMODE; - else if(G.f & G_WEIGHTPAINT) - arm->flag |= ARM_POSEMODE; - + else if(G.f & G_WEIGHTPAINT) { + if(OBACT && ob==modifiers_isDeformedByArmature(OBACT)) + arm->flag |= ARM_POSEMODE; + } draw_pose_paths(scene, v3d, ob); } } diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index d8025698f02..fa90730fb05 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -142,9 +142,10 @@ void ED_view3d_exit_paint_modes(bContext *C) { if(G.f & G_VERTEXPAINT) WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); + else if(G.f & G_VERTEXPAINT) + WM_operator_name_call(C, "VIEW3D_OT_wpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); // if(G.f & G_TEXTUREPAINT) set_texturepaint(); -// if(G.f & G_WEIGHTPAINT) set_wpaint(); // if(G.f & G_SCULPTMODE) set_sculptmode(); // if(G.f & G_PARTICLEEDIT) PE_set_particle_edit(); @@ -5434,7 +5435,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ -// XXX set_wpaint(); + WM_operator_name_call(C, "VIEW3D_OT_wpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); } } else if (v3d->modeselect == V3D_POSEMODE_SEL) { diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 8fc00ffd538..baf5a849bd4 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -122,6 +122,8 @@ void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc); /* vpaint.c */ void VIEW3D_OT_vpaint_toggle(struct wmOperatorType *ot); void VIEW3D_OT_vpaint(struct wmOperatorType *ot); +void VIEW3D_OT_wpaint_toggle(struct wmOperatorType *ot); +void VIEW3D_OT_wpaint(struct wmOperatorType *ot); /* view3d_view.c */ void VIEW3D_OT_smoothview(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index da4b752f370..3bc3cd76341 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -80,7 +80,9 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_setcameratoview); WM_operatortype_append(VIEW3D_OT_drawtype); WM_operatortype_append(VIEW3D_OT_vpaint_toggle); + WM_operatortype_append(VIEW3D_OT_wpaint_toggle); WM_operatortype_append(VIEW3D_OT_vpaint); + WM_operatortype_append(VIEW3D_OT_wpaint); transform_operatortypes(); } @@ -92,6 +94,7 @@ void view3d_keymap(wmWindowManager *wm) /* paint poll checks mode */ WM_keymap_verify_item(keymap, "VIEW3D_OT_vpaint", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_wpaint", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0); @@ -155,6 +158,7 @@ void view3d_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "VIEW3D_OT_set_camera_to_view", PAD0, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_vpaint_toggle", VKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_wpaint_toggle", TABKEY, KM_PRESS, KM_CTRL, 0); /* TODO - this is just while we have no way to load a text datablock */ RNA_string_set(WM_keymap_add_item(keymap, "SCRIPT_OT_run_pyfile", PKEY, KM_PRESS, 0, 0)->ptr, "filename", "test.py"); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 6664ac11877..2a6d7f3269a 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1067,14 +1067,14 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter) basact->flag|= SELECT; basact->object->flag= basact->flag; + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, basact->object); + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, basact->object); + /* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */ if(G.f & G_WEIGHTPAINT) { /* prevent activating */ basact= NULL; } - - WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, basact->object); - WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, basact->object); } /* prevent bone selecting to pass on to object selecting */ @@ -1449,7 +1449,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) while (base->selcol == (*col & 0xFFFF)) { /* we got an object */ if(*col & 0xFFFF0000) { /* we got a bone */ - bone = NULL; // XXX get_indexed_bone(base->object, *col & ~(BONESEL_ANY)); + bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY)); if(bone) { if(selecting) { bone->flag |= BONE_SELECTED; diff --git a/source/blender/editors/space_view3d/vpaint.c b/source/blender/editors/space_view3d/vpaint.c index f253612259f..73d0096739c 100644 --- a/source/blender/editors/space_view3d/vpaint.c +++ b/source/blender/editors/space_view3d/vpaint.c @@ -90,7 +90,7 @@ #include "view3d_intern.h" - /* Gvp.mode */ + /* vp->mode */ #define VP_MIX 0 #define VP_ADD 1 #define VP_SUB 2 @@ -104,24 +104,32 @@ /* XXX */ static void BIF_undo_push() {} static void error() {} -static int get_mbut() {return 0;} -VPaint Gvp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT+VP_SPRAY, 0}; -VPaint Gwp= {1.0, 1.0, 1.0, 1.0, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT, 0}; +static VPaint *new_vpaint(int wpaint) +{ + VPaint *vp= MEM_callocN(sizeof(VPaint), "VPaint"); + + vp->r= 1.0f; + vp->g= 1.0f; + vp->b= 1.0f; + vp->a= 0.2f; + vp->size= 25.0f; + vp->gamma= vp->mul= 1.0f; + + vp->flag= VP_AREA+VP_SOFT+VP_SPRAY; + + if(wpaint) { + vp->a= 1.0f; + vp->flag= VP_AREA+VP_SOFT; + } + return vp; +} static int *get_indexarray(void) { return MEM_mallocN(sizeof(int)*MAXINDEX + 2, "vertexpaint"); } -void free_vertexpaint() -{ - - if(Gvp.vpaint_prev) MEM_freeN(Gvp.vpaint_prev); - Gvp.vpaint_prev= NULL; - - mesh_octree_table(NULL, NULL, NULL, 'e'); -} /* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte! so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */ @@ -269,18 +277,18 @@ static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot) } -static void copy_wpaint_prev (VPaint *vp, MDeformVert *dverts, int dcount) +static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount) { - if (vp->wpaint_prev) { - free_dverts(vp->wpaint_prev, vp->tot); - vp->wpaint_prev= NULL; + if (wp->wpaint_prev) { + free_dverts(wp->wpaint_prev, wp->tot); + wp->wpaint_prev= NULL; } if(dverts && dcount) { - vp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev"); - vp->tot = dcount; - copy_dverts (vp->wpaint_prev, dverts, dcount); + wp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev"); + wp->tot = dcount; + copy_dverts (wp->wpaint_prev, dverts, dcount); } } @@ -300,7 +308,7 @@ void clear_vpaint(Scene *scene) if(me==0 || me->mcol==0 || me->totface==0) return; - paintcol= vpaint_get_current_col(&Gvp); + paintcol= vpaint_get_current_col(scene->toolsettings->vpaint); to= (unsigned int *)me->mcol; a= 4*me->totface; @@ -328,7 +336,7 @@ void clear_vpaint_selectedfaces(Scene *scene) if(!me->mcol) make_vertexcol(scene, 0); - paintcol= vpaint_get_current_col(&Gvp); + paintcol= vpaint_get_current_col(scene->toolsettings->vpaint); mf = me->mface; mcol = (unsigned int*)me->mcol; @@ -349,6 +357,7 @@ void clear_vpaint_selectedfaces(Scene *scene) /* fills in the selected faces with the current weight and vertex group */ void clear_wpaint_selectedfaces(Scene *scene) { + VPaint *wp= scene->toolsettings->wpaint; float editbutvweight; float paintweight= editbutvweight; Mesh *me; @@ -377,7 +386,7 @@ void clear_wpaint_selectedfaces(Scene *scene) /* directly copied from weight_paint, should probaby split into a seperate function */ /* if mirror painting, find the other group */ - if(Gwp.flag & VP_MIRROR_X) { + if(wp->flag & VP_MIRROR_X) { bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1); if(defgroup) { bDeformGroup *curdef; @@ -402,7 +411,7 @@ void clear_wpaint_selectedfaces(Scene *scene) } /* end copy from weight_paint*/ - copy_wpaint_prev(&Gwp, me->dvert, me->totvert); + copy_wpaint_prev(wp, me->dvert, me->totvert); for(index=0; index<me->totface; index++) { if(indexar[index] && indexar[index]<=me->totface) { @@ -416,20 +425,20 @@ void clear_wpaint_selectedfaces(Scene *scene) if(!((me->dvert+faceverts[i])->flag)) { dw= verify_defweight(me->dvert+faceverts[i], vgroup); if(dw) { - uw= verify_defweight(Gwp.wpaint_prev+faceverts[i], vgroup); + uw= verify_defweight(wp->wpaint_prev+faceverts[i], vgroup); uw->weight= dw->weight; /* set the undio weight */ dw->weight= paintweight; - if(Gwp.flag & VP_MIRROR_X) { /* x mirror painting */ + if(wp->flag & VP_MIRROR_X) { /* x mirror painting */ int j= mesh_get_x_mirror_vert(ob, faceverts[i]); if(j>=0) { /* copy, not paint again */ if(vgroup_mirror != -1) { dw= verify_defweight(me->dvert+j, vgroup_mirror); - uw= verify_defweight(Gwp.wpaint_prev+j, vgroup_mirror); + uw= verify_defweight(wp->wpaint_prev+j, vgroup_mirror); } else { dw= verify_defweight(me->dvert+j, vgroup); - uw= verify_defweight(Gwp.wpaint_prev+j, vgroup); + uw= verify_defweight(wp->wpaint_prev+j, vgroup); } uw->weight= dw->weight; /* set the undo weight */ dw->weight= paintweight; @@ -449,7 +458,7 @@ void clear_wpaint_selectedfaces(Scene *scene) } MEM_freeN(indexar); - copy_wpaint_prev(&Gwp, NULL, 0); + copy_wpaint_prev(wp, NULL, 0); DAG_object_flush_update(scene, ob, OB_RECALC_DATA); BIF_undo_push("Set vertex weight"); @@ -458,6 +467,7 @@ void clear_wpaint_selectedfaces(Scene *scene) void vpaint_dogamma(Scene *scene) { + VPaint *vp= scene->toolsettings->vpaint; Mesh *me; Object *ob; float igam, fac; @@ -470,11 +480,11 @@ void vpaint_dogamma(Scene *scene) me= get_mesh(ob); if(me==0 || me->mcol==0 || me->totface==0) return; - igam= 1.0/Gvp.gamma; + igam= 1.0/vp->gamma; for(a=0; a<256; a++) { fac= ((float)a)/255.0; - fac= Gvp.mul*pow( fac, igam); + fac= vp->mul*pow( fac, igam); temp= 255.9*fac; @@ -498,6 +508,7 @@ void vpaint_dogamma(Scene *scene) /* used for both 3d view and image window */ void sample_vpaint(Scene *scene, ARegion *ar) /* frontbuf */ { + VPaint *vp= scene->toolsettings->vpaint; unsigned int col; int x, y; short mval[2]; @@ -519,9 +530,9 @@ void sample_vpaint(Scene *scene, ARegion *ar) /* frontbuf */ cp = (char *)&col; if(G.f & (G_VERTEXPAINT|G_WEIGHTPAINT)) { - Gvp.r= cp[0]/255.0f; - Gvp.g= cp[1]/255.0f; - Gvp.b= cp[2]/255.0f; + vp->r= cp[0]/255.0f; + vp->g= cp[1]/255.0f; + vp->b= cp[2]/255.0f; } else { Brush *brush= scene->toolsettings->imapaint.brush; @@ -684,29 +695,29 @@ static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac) return col; } -static void vpaint_blend( unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha) +static void vpaint_blend(VPaint *vp, unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha) { - if(Gvp.mode==VP_MIX || Gvp.mode==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha); - else if(Gvp.mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha); - else if(Gvp.mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha); - else if(Gvp.mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha); - else if(Gvp.mode==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha); - else if(Gvp.mode==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha); + if(vp->mode==VP_MIX || vp->mode==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha); + else if(vp->mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha); + else if(vp->mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha); + else if(vp->mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha); + else if(vp->mode==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha); + else if(vp->mode==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha); /* if no spray, clip color adding with colorig & orig alpha */ - if((Gvp.flag & VP_SPRAY)==0) { + if((vp->flag & VP_SPRAY)==0) { unsigned int testcol=0, a; char *cp, *ct, *co; - alpha= (int)(255.0*Gvp.a); + alpha= (int)(255.0*vp->a); - if(Gvp.mode==VP_MIX || Gvp.mode==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha); - else if(Gvp.mode==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha); - else if(Gvp.mode==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha); - else if(Gvp.mode==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha); - else if(Gvp.mode==VP_LIGHTEN) testcol= mcol_lighten( *colorig, paintcol, alpha); - else if(Gvp.mode==VP_DARKEN) testcol= mcol_darken( *colorig, paintcol, alpha); + if(vp->mode==VP_MIX || vp->mode==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha); + else if(vp->mode==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha); + else if(vp->mode==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha); + else if(vp->mode==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha); + else if(vp->mode==VP_LIGHTEN) testcol= mcol_lighten( *colorig, paintcol, alpha); + else if(vp->mode==VP_DARKEN) testcol= mcol_darken( *colorig, paintcol, alpha); cp= (char *)col; ct= (char *)&testcol; @@ -802,49 +813,49 @@ static int calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], floa return alpha; } -static void wpaint_blend(MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval) +static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval) { if(dw==NULL || uw==NULL) return; - if(Gwp.mode==VP_MIX || Gwp.mode==VP_BLUR) + if(wp->mode==VP_MIX || wp->mode==VP_BLUR) dw->weight = paintval*alpha + dw->weight*(1.0-alpha); - else if(Gwp.mode==VP_ADD) + else if(wp->mode==VP_ADD) dw->weight += paintval*alpha; - else if(Gwp.mode==VP_SUB) + else if(wp->mode==VP_SUB) dw->weight -= paintval*alpha; - else if(Gwp.mode==VP_MUL) + else if(wp->mode==VP_MUL) /* first mul, then blend the fac */ dw->weight = ((1.0-alpha) + alpha*paintval)*dw->weight; - else if(Gwp.mode==VP_LIGHTEN) { + else if(wp->mode==VP_LIGHTEN) { if (dw->weight < paintval) dw->weight = paintval*alpha + dw->weight*(1.0-alpha); - } else if(Gwp.mode==VP_DARKEN) { + } else if(wp->mode==VP_DARKEN) { if (dw->weight > paintval) dw->weight = paintval*alpha + dw->weight*(1.0-alpha); } CLAMP(dw->weight, 0.0f, 1.0f); /* if no spray, clip result with orig weight & orig alpha */ - if((Gwp.flag & VP_SPRAY)==0) { + if((wp->flag & VP_SPRAY)==0) { float testw=0.0f; - alpha= Gwp.a; - if(Gwp.mode==VP_MIX || Gwp.mode==VP_BLUR) + alpha= wp->a; + if(wp->mode==VP_MIX || wp->mode==VP_BLUR) testw = paintval*alpha + uw->weight*(1.0-alpha); - else if(Gwp.mode==VP_ADD) + else if(wp->mode==VP_ADD) testw = uw->weight + paintval*alpha; - else if(Gwp.mode==VP_SUB) + else if(wp->mode==VP_SUB) testw = uw->weight - paintval*alpha; - else if(Gwp.mode==VP_MUL) + else if(wp->mode==VP_MUL) /* first mul, then blend the fac */ testw = ((1.0-alpha) + alpha*paintval)*uw->weight; - else if(Gwp.mode==VP_LIGHTEN) { + else if(wp->mode==VP_LIGHTEN) { if (uw->weight < paintval) testw = paintval*alpha + uw->weight*(1.0-alpha); else testw = uw->weight; - } else if(Gwp.mode==VP_DARKEN) { + } else if(wp->mode==VP_DARKEN) { if (uw->weight > paintval) testw = paintval*alpha + uw->weight*(1.0-alpha); else @@ -872,7 +883,7 @@ static void wpaint_blend(MDeformWeight *dw, MDeformWeight *uw, float alpha, floa /* else */ /* sets editbutvweight to the closest weight value to vertex */ /* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */ -static void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) +void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) { ViewContext vc; Object *ob= OBACT; @@ -1009,26 +1020,26 @@ static void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) } -static void do_weight_paint_vertex(Object *ob, int index, int alpha, float paintweight, int vgroup_mirror) +static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, float paintweight, int vgroup_mirror) { Mesh *me= ob->data; - MDeformWeight *dw, *uw; + MDeformWeight *dw, *uw; int vgroup= ob->actdef-1; - if(Gwp.flag & VP_ONLYVGROUP) { + if(wp->flag & VP_ONLYVGROUP) { dw= get_defweight(me->dvert+index, vgroup); - uw= get_defweight(Gwp.wpaint_prev+index, vgroup); + uw= get_defweight(wp->wpaint_prev+index, vgroup); } else { dw= verify_defweight(me->dvert+index, vgroup); - uw= verify_defweight(Gwp.wpaint_prev+index, vgroup); + uw= verify_defweight(wp->wpaint_prev+index, vgroup); } if(dw==NULL || uw==NULL) return; - wpaint_blend(dw, uw, (float)alpha/255.0, paintweight); + wpaint_blend(wp, dw, uw, (float)alpha/255.0, paintweight); - if(Gwp.flag & VP_MIRROR_X) { /* x mirror painting */ + if(wp->flag & VP_MIRROR_X) { /* x mirror painting */ int j= mesh_get_x_mirror_vert(ob, index); if(j>=0) { /* copy, not paint again */ @@ -1043,150 +1054,222 @@ static void do_weight_paint_vertex(Object *ob, int index, int alpha, float paint } -void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) +/* *************** set wpaint operator ****************** */ +/* retrieve whether cursor should be set or operator should be done */ +static int wp_poll(bContext *C) { - ViewContext vc; - float editbutvweight; // XXX - Object *ob; - Mesh *me; - MFace *mface; - float mat[4][4], imat[4][4], paintweight, *vertexcosnos; - float vpimat[3][3]; - int *indexar, index, totindex, alpha, totw; - int vgroup_mirror= -1; - short mval[2], mvalo[2], firsttime=1; + if(G.f & G_WEIGHTPAINT) { + ScrArea *sa= CTX_wm_area(C); + if(sa->spacetype==SPACE_VIEW3D) { + ARegion *ar= CTX_wm_region(C); + if(ar->regiontype==RGN_TYPE_WINDOW) + return 1; + } + } + return 0; +} + +static void wp_drawcursor(bContext *C, int x, int y) +{ + ToolSettings *ts= CTX_data_tool_settings(C); - if((G.f & G_WEIGHTPAINT)==0) return; - if(scene->obedit) return; -// XXX if(multires_level1_test()) return; + glTranslatef((float)x, (float)y, 0.0f); - ob= OBACT; - if(!ob || ob->id.lib) return; + glColor4ub(200, 200, 255, 128); + glEnable( GL_LINE_SMOOTH ); + glEnable(GL_BLEND); + glutil_draw_lined_arc(0.0, M_PI*2.0, ts->wpaint->size, 40); + glDisable(GL_BLEND); + glDisable( GL_LINE_SMOOTH ); + + glTranslatef((float)-x, (float)-y, 0.0f); +} +static int set_wpaint(bContext *C, wmOperator *op) /* toggle */ +{ + Object *ob= CTX_data_active_object(C); + Scene *scene= CTX_data_scene(C); + VPaint *wp= scene->toolsettings->wpaint; + Mesh *me; + me= get_mesh(ob); - if(me==NULL || me->totface==0) return; + if(ob->id.lib || me==NULL) return OPERATOR_CANCELLED; - /* if nothing was added yet, we make dverts and a vertex deform group */ -// if (!me->dvert) -// create_dverts(&me->id); - -// if(qual & LR_CTRLKEY) { - sample_wpaint(scene, ar, v3d, 0); -// return; -// } -// if(qual & LR_SHIFTKEY) { -// sample_wpaint(scene, ar, v3d, 1); -// return; -// } + if(me && me->totface>=MAXINDEX) { + error("Maximum number of faces: %d", MAXINDEX-1); + G.f &= ~G_WEIGHTPAINT; + return OPERATOR_CANCELLED; + } - /* ALLOCATIONS! no return after this line */ - /* painting on subsurfs should give correct points too, this returns me->totvert amount */ - vertexcosnos= mesh_get_mapped_verts_nors(scene, ob); - indexar= get_indexarray(); - copy_wpaint_prev(&Gwp, me->dvert, me->totvert); - - /* this happens on a Bone select, when no vgroup existed yet */ - if(ob->actdef<=0) { - Object *modob; - if((modob = modifiers_isDeformedByArmature(ob))) { + if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT; + else G.f |= G_WEIGHTPAINT; + + + /* Weightpaint works by overriding colors in mesh, + * so need to make sure we recalc on enter and + * exit (exit needs doing regardless because we + * should redeform). + */ + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + + if(G.f & G_WEIGHTPAINT) { + Object *par; + + if(wp==NULL) + wp= scene->toolsettings->wpaint= new_vpaint(1); + + wp->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), wp_poll, wp_drawcursor); + + mesh_octree_table(ob, NULL, NULL, 's'); + + /* verify if active weight group is also active bone */ + par= modifiers_isDeformedByArmature(ob); + if(par && (par->flag & OB_POSEMODE)) { bPoseChannel *pchan; - for(pchan= modob->pose->chanbase.first; pchan; pchan= pchan->next) - if(pchan->bone->flag & SELECT) + for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next) + if(pchan->bone->flag & BONE_ACTIVE) break; - if(pchan) { - bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name); - if(dg==NULL) - dg= add_defgroup_name(ob, pchan->name); /* sets actdef */ - else - ob->actdef= get_defgroup_num(ob, dg); - } + if(pchan) + vertexgroup_select_by_name(ob, pchan->name); } } - if(ob->defbase.first==NULL) { - add_defgroup(ob); - } - - if(ob->lay & v3d->lay); else error("Active object is not in this layer"); + else { + if(wp) + WM_paint_cursor_end(CTX_wm_manager(C), wp->paintcursor); + + mesh_octree_table(ob, NULL, NULL, 'e'); + } -// XXX persp(PERSP_VIEW); - /* imat for normals */ - Mat4MulMat4(mat, ob->obmat, v3d->viewmat); - Mat4Invert(imat, mat); - Mat3CpyMat4(vpimat, imat); + WM_event_add_notifier(C, NC_SCENE|ND_MODE, ob); - /* load projection matrix */ - wmMultMatrix(ob->obmat); - wmGetSingleMatrix(mat); - wmLoadMatrix(v3d->viewmat); + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_wpaint_toggle(wmOperatorType *ot) +{ -// getmouseco_areawin(mvalo); + /* identifiers */ + ot->name= "Weight Paint Mode"; + ot->idname= "VIEW3D_OT_wpaint_toggle"; -// getmouseco_areawin(mval); - mvalo[0]= mval[0]; - mvalo[1]= mval[1]; + /* api callbacks */ + ot->exec= set_wpaint; + ot->poll= ED_operator_object_active; - /* if mirror painting, find the other group */ - if(Gwp.flag & VP_MIRROR_X) { - bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1); - if(defgroup) { - bDeformGroup *curdef; - int actdef= 0; - char name[32]; +} - BLI_strncpy(name, defgroup->name, 32); - bone_flip_name(name, 0); /* 0 = don't strip off number extensions */ - - for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++) - if (!strcmp(curdef->name, name)) +/* ************ weight paint operator ********** */ + +struct WPaintData { + ViewContext vc; + int *indexar; + int vgroup_mirror; + float *vertexcosnos; + float wpimat[3][3]; +}; + +static void wpaint_exit(bContext *C, wmOperator *op) +{ + ToolSettings *ts= CTX_data_tool_settings(C); + Object *ob= CTX_data_active_object(C); + struct WPaintData *wpd= op->customdata; + + if(wpd->vertexcosnos) + MEM_freeN(wpd->vertexcosnos); + MEM_freeN(wpd->indexar); + + /* frees prev buffer */ + copy_wpaint_prev(ts->wpaint, NULL, 0); + + /* and particles too */ + if(ob->particlesystem.first) { + ParticleSystem *psys; + int i; + + for(psys= ob->particlesystem.first; psys; psys= psys->next) { + for(i=0; i<PSYS_TOT_VG; i++) { + if(psys->vgroup[i]==ob->actdef) { + psys->recalc |= PSYS_RECALC_HAIR; break; - if(curdef==NULL) { - int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */ - curdef= add_defgroup_name (ob, name); - ob->actdef= olddef; + } } - - if(curdef && curdef!=defgroup) - vgroup_mirror= actdef; } } - while (get_mbut() & 0) { -// getmouseco_areawin(mval); - - if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { - firsttime= 0; + DAG_object_flush_update(CTX_data_scene(C), ob, OB_RECALC_DATA); + + ED_undo_push(C, "Weight Paint"); + + MEM_freeN(wpd); + op->customdata= NULL; +} + + +static int wpaint_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + ToolSettings *ts= CTX_data_tool_settings(C); + VPaint *wp= ts->wpaint; + float editbutvweight= 1.0f; // XXX + + switch(event->type) { + case LEFTMOUSE: + if(event->val==0) { /* release */ + wpaint_exit(C, op); + return OPERATOR_FINISHED; + } + /* pass on, first press gets painted too */ + + case MOUSEMOVE: + { + struct WPaintData *wpd= op->customdata; + ViewContext *vc= &wpd->vc; + Object *ob= vc->obact; + Mesh *me= ob->data; + float mat[4][4]; + float paintweight= editbutvweight; // XXX + int *indexar= wpd->indexar; + int totindex, index, alpha, totw; + short mval[2]; + + view3d_operator_needs_opengl(C); + + /* load projection matrix */ + wmMultMatrix(ob->obmat); + wmGetSingleMatrix(mat); + wmLoadMatrix(wpd->vc.v3d->viewmat); + + MTC_Mat4SwapMat4(wpd->vc.v3d->persmat, mat); + + mval[0]= event->x - vc->ar->winrct.xmin; + mval[1]= event->y - vc->ar->winrct.ymin; /* which faces are involved */ - if(Gwp.flag & VP_AREA) { - totindex= sample_backbuf_area(&vc, indexar, me->totface, mval[0], mval[1], Gwp.size); + if(wp->flag & VP_AREA) { + totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], wp->size); } else { - indexar[0]= view3d_sample_backbuf(&vc, mval[0], mval[1]); + indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); if(indexar[0]) totindex= 1; else totindex= 0; } - MTC_Mat4SwapMat4(v3d->persmat, mat); - - if(Gwp.flag & VP_COLINDEX) { + if(wp->flag & VP_COLINDEX) { for(index=0; index<totindex; index++) { if(indexar[index] && indexar[index]<=me->totface) { - - mface= ((MFace *)me->mface) + (indexar[index]-1); - + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + if(mface->mat_nr!=ob->actcol-1) { indexar[index]= 0; } } } } - + if((G.f & G_FACESELECT) && me->mface) { for(index=0; index<totindex; index++) { if(indexar[index] && indexar[index]<=me->totface) { - - mface= ((MFace *)me->mface) + (indexar[index]-1); - + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + if((mface->flag & ME_FACE_SEL)==0) { indexar[index]= 0; } @@ -1197,24 +1280,24 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) /* make sure each vertex gets treated only once */ /* and calculate filter weight */ totw= 0; - if(Gwp.mode==VP_BLUR) + if(wp->mode==VP_BLUR) paintweight= 0.0f; else paintweight= editbutvweight; for(index=0; index<totindex; index++) { if(indexar[index] && indexar[index]<=me->totface) { - mface= me->mface + (indexar[index]-1); + 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; - if(Gwp.mode==VP_BLUR) { + if(wp->mode==VP_BLUR) { MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = verify_defweight; - if(Gwp.flag & VP_ONLYVGROUP) + if(wp->flag & VP_ONLYVGROUP) dw_func= get_defweight; dw= dw_func(me->dvert+mface->v1, ob->actdef-1); @@ -1231,43 +1314,43 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) } } - if(Gwp.mode==VP_BLUR) + if(wp->mode==VP_BLUR) paintweight/= (float)totw; for(index=0; index<totindex; index++) { if(indexar[index] && indexar[index]<=me->totface) { - mface= me->mface + (indexar[index]-1); + MFace *mface= me->mface + (indexar[index]-1); if((me->dvert+mface->v1)->flag) { - alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v1, mval); + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval); if(alpha) { - do_weight_paint_vertex(ob, mface->v1, alpha, paintweight, vgroup_mirror); + do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror); } (me->dvert+mface->v1)->flag= 0; } if((me->dvert+mface->v2)->flag) { - alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v2, mval); + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval); if(alpha) { - do_weight_paint_vertex(ob, mface->v2, alpha, paintweight, vgroup_mirror); + do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror); } (me->dvert+mface->v2)->flag= 0; } if((me->dvert+mface->v3)->flag) { - alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v3, mval); + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval); if(alpha) { - do_weight_paint_vertex(ob, mface->v3, alpha, paintweight, vgroup_mirror); + do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror); } (me->dvert+mface->v3)->flag= 0; } if((me->dvert+mface->v4)->flag) { if(mface->v4) { - alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v4, mval); + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval); if(alpha) { - do_weight_paint_vertex(ob, mface->v4, alpha, paintweight, vgroup_mirror); + do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror); } (me->dvert+mface->v4)->flag= 0; } @@ -1275,104 +1358,134 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) } } - MTC_Mat4SwapMat4(v3d->persmat, mat); - - } - - if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { - - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + MTC_Mat4SwapMat4(vc->v3d->persmat, mat); - if(Gwp.flag & (VP_AREA|VP_SOFT)) { - /* draw circle in backbuf! */ -// XXX persp(PERSP_WIN); -// XXX fdrawXORcirc((float)mval[0], (float)mval[1], Gwp.size); -// XXX persp(PERSP_VIEW); - } - - mvalo[0]= mval[0]; - mvalo[1]= mval[1]; + DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA); + ED_region_tag_redraw(vc->ar); } } - - if(vertexcosnos) - MEM_freeN(vertexcosnos); - MEM_freeN(indexar); - copy_wpaint_prev(&Gwp, NULL, 0); - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); - - /* and particles too */ - if(ob->particlesystem.first) { - ParticleSystem *psys; - int i; - - psys= ob->particlesystem.first; - while(psys) { - for(i=0; i<PSYS_TOT_VG; i++) { - if(psys->vgroup[i]==ob->actdef) { - psys->recalc |= PSYS_RECALC_HAIR; - break; - } - } - - psys= psys->next; - } - } - - BIF_undo_push("Weight Paint"); + return OPERATOR_RUNNING_MODAL; } -void set_wpaint(bContext *C, wmOperator *op) /* toggle */ -{ - Object *ob= CTX_data_active_object(C); +static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ Scene *scene= CTX_data_scene(C); + ToolSettings *ts= CTX_data_tool_settings(C); + VPaint *wp= ts->wpaint; + Object *ob= CTX_data_active_object(C); + struct WPaintData *wpd; Mesh *me; + float mat[4][4], imat[4][4]; - ob= OBACT; - if(!ob || ob->id.lib) return; - me= get_mesh(ob); + if(scene->obedit) return OPERATOR_CANCELLED; + // XXX if(multires_level1_test()) return; - if(me && me->totface>=MAXINDEX) { - error("Maximum number of faces: %d", MAXINDEX-1); - G.f &= ~G_WEIGHTPAINT; - return; - } + me= get_mesh(ob); + if(me==NULL || me->totface==0) return OPERATOR_CANCELLED; - if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT; - else G.f |= G_WEIGHTPAINT; + /* if nothing was added yet, we make dverts and a vertex deform group */ + if (!me->dvert) + create_dverts(&me->id); + /* make customdata storage */ + op->customdata= wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData"); + view3d_set_viewcontext(C, &wpd->vc); + wpd->vgroup_mirror= -1; + + // if(qual & LR_CTRLKEY) { + // sample_wpaint(scene, ar, v3d, 0); + // return; + // } + // if(qual & LR_SHIFTKEY) { + // sample_wpaint(scene, ar, v3d, 1); + // return; + // } - /* Weightpaint works by overriding colors in mesh, - * so need to make sure we recalc on enter and - * exit (exit needs doing regardless because we - * should redeform). - */ - if (me) { - DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA); - } + /* ALLOCATIONS! no return after this line */ + /* painting on subsurfs should give correct points too, this returns me->totvert amount */ + wpd->vertexcosnos= mesh_get_mapped_verts_nors(scene, ob); + wpd->indexar= get_indexarray(); + copy_wpaint_prev(wp, me->dvert, me->totvert); - if(G.f & G_WEIGHTPAINT) { - Object *par; - - mesh_octree_table(ob, NULL, NULL, 's'); - - /* verify if active weight group is also active bone */ - par= modifiers_isDeformedByArmature(ob); - if(par && (par->flag & OB_POSEMODE)) { + /* this happens on a Bone select, when no vgroup existed yet */ + if(ob->actdef<=0) { + Object *modob; + if((modob = modifiers_isDeformedByArmature(ob))) { bPoseChannel *pchan; - for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next) - if(pchan->bone->flag & BONE_ACTIVE) + for(pchan= modob->pose->chanbase.first; pchan; pchan= pchan->next) + if(pchan->bone->flag & SELECT) break; - // if(pchan) - // XXX vertexgroup_select_by_name(ob, pchan->name); + if(pchan) { + bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name); + if(dg==NULL) + dg= add_defgroup_name(ob, pchan->name); /* sets actdef */ + else + ob->actdef= get_defgroup_num(ob, dg); + } } } - else { - mesh_octree_table(ob, NULL, NULL, 'e'); + if(ob->defbase.first==NULL) { + add_defgroup(ob); + } + + // if(ob->lay & v3d->lay); else error("Active object is not in this layer"); + + /* imat for normals */ + Mat4MulMat4(mat, ob->obmat, wpd->vc.v3d->viewmat); + Mat4Invert(imat, mat); + Mat3CpyMat4(wpd->wpimat, imat); + + /* if mirror painting, find the other group */ + if(wp->flag & VP_MIRROR_X) { + bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1); + if(defgroup) { + bDeformGroup *curdef; + int actdef= 0; + char name[32]; + + BLI_strncpy(name, defgroup->name, 32); + bone_flip_name(name, 0); /* 0 = don't strip off number extensions */ + + for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++) + if (!strcmp(curdef->name, name)) + break; + if(curdef==NULL) { + int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */ + curdef= add_defgroup_name (ob, name); + ob->actdef= olddef; + } + + if(curdef && curdef!=defgroup) + wpd->vgroup_mirror= actdef; + } } + + /* do paint once for click only paint */ + wpaint_modal(C, op, event); + + /* add modal handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + + return OPERATOR_RUNNING_MODAL; +} + +void VIEW3D_OT_wpaint(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Weight Paint"; + ot->idname= "VIEW3D_OT_wpaint"; + + /* api callbacks */ + ot->invoke= wpaint_invoke; + ot->modal= wpaint_modal; + /* ot->exec= vpaint_exec; <-- needs stroke property */ + ot->poll= wp_poll; + } + /* ************ set / clear vertex paint mode ********** */ /* retrieve whether cursor should be set or operator should be done */ @@ -1391,12 +1504,14 @@ static int vp_poll(bContext *C) static void vp_drawcursor(bContext *C, int x, int y) { + ToolSettings *ts= CTX_data_tool_settings(C); + glTranslatef((float)x, (float)y, 0.0f); glColor4ub(255, 255, 255, 128); glEnable( GL_LINE_SMOOTH ); glEnable(GL_BLEND); - glutil_draw_lined_arc(0.0, M_PI*2.0, Gvp.size, 40); + glutil_draw_lined_arc(0.0, M_PI*2.0, ts->vpaint->size, 40); glDisable(GL_BLEND); glDisable( GL_LINE_SMOOTH ); @@ -1407,6 +1522,7 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ { Object *ob= CTX_data_active_object(C); Scene *scene= CTX_data_scene(C); + VPaint *vp= scene->toolsettings->vpaint; Mesh *me; if(object_data_is_libdata(ob)) { @@ -1425,19 +1541,26 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ if(me && me->mcol==NULL) make_vertexcol(scene, 0); /* toggle: end vpaint */ - if(G.f & G_VERTEXPAINT){ + if(G.f & G_VERTEXPAINT) { + G.f &= ~G_VERTEXPAINT; - WM_paint_cursor_end(CTX_wm_manager(C), Gvp.paintcursor); - Gvp.paintcursor= NULL; + if(vp) { + WM_paint_cursor_end(CTX_wm_manager(C), vp->paintcursor); + vp->paintcursor= NULL; + } } else { + G.f |= G_VERTEXPAINT; /* Turn off weight painting */ if (G.f & G_WEIGHTPAINT) set_wpaint(C, op); - Gvp.paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), vp_poll, vp_drawcursor); + if(vp==NULL) + vp= scene->toolsettings->vpaint= new_vpaint(0); + + vp->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), vp_poll, vp_drawcursor); } if (me) @@ -1453,7 +1576,7 @@ void VIEW3D_OT_vpaint_toggle(wmOperatorType *ot) { /* identifiers */ - ot->name= "Vpaint mode"; + ot->name= "Vertex Paint Mode"; ot->idname= "VIEW3D_OT_vpaint_toggle"; /* api callbacks */ @@ -1481,8 +1604,7 @@ Operator->modal() For future: - implement a stroke event (or mousemove with past positons) - - revise whether customdata should be added in object, in set_vpaint - - store Gvp locally (in scene?) + - revise whether op->customdata should be added in object, in set_vpaint */ @@ -1496,6 +1618,7 @@ struct VPaintData { static void vpaint_exit(bContext *C, wmOperator *op) { + ToolSettings *ts= CTX_data_tool_settings(C); struct VPaintData *vpd= op->customdata; if(vpd->vertexcosnos) @@ -1503,7 +1626,7 @@ static void vpaint_exit(bContext *C, wmOperator *op) MEM_freeN(vpd->indexar); /* frees prev buffer */ - copy_vpaint_prev(&Gvp, NULL, 0); + copy_vpaint_prev(ts->vpaint, NULL, 0); ED_undo_push(C, "Vertex Paint"); @@ -1513,6 +1636,8 @@ static void vpaint_exit(bContext *C, wmOperator *op) static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) { + ToolSettings *ts= CTX_data_tool_settings(C); + VPaint *vp= ts->vpaint; switch(event->type) { case LEFTMOUSE: @@ -1544,8 +1669,8 @@ static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) mval[1]= event->y - vc->ar->winrct.ymin; /* which faces are involved */ - if(Gvp.flag & VP_AREA) { - totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], Gvp.size); + if(vp->flag & VP_AREA) { + totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], vp->size); } else { indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); @@ -1555,7 +1680,7 @@ static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) MTC_Mat4SwapMat4(vc->v3d->persmat, mat); - if(Gvp.flag & VP_COLINDEX) { + if(vp->flag & VP_COLINDEX) { for(index=0; index<totindex; index++) { if(indexar[index] && indexar[index]<=me->totface) { MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); @@ -1582,10 +1707,10 @@ static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) if(indexar[index] && indexar[index]<=me->totface) { MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); unsigned int *mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1); - unsigned int *mcolorig= ( (unsigned int *)Gvp.vpaint_prev) + 4*(indexar[index]-1); + unsigned int *mcolorig= ( (unsigned int *)vp->vpaint_prev) + 4*(indexar[index]-1); int alpha; - if(Gvp.mode==VP_BLUR) { + if(vp->mode==VP_BLUR) { unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128); if(mface->v4) { unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128); @@ -1597,18 +1722,18 @@ static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) } - alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v1, mval); - if(alpha) vpaint_blend( mcol, mcolorig, vpd->paintcol, alpha); + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v1, mval); + if(alpha) vpaint_blend(vp, mcol, mcolorig, vpd->paintcol, alpha); - alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v2, mval); - if(alpha) vpaint_blend( mcol+1, mcolorig+1, vpd->paintcol, alpha); + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v2, mval); + if(alpha) vpaint_blend(vp, mcol+1, mcolorig+1, vpd->paintcol, alpha); - alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v3, mval); - if(alpha) vpaint_blend( mcol+2, mcolorig+2, vpd->paintcol, alpha); + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v3, mval); + if(alpha) vpaint_blend(vp, mcol+2, mcolorig+2, vpd->paintcol, alpha); if(mface->v4) { - alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v4, mval); - if(alpha) vpaint_blend( mcol+3, mcolorig+3, vpd->paintcol, alpha); + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v4, mval); + if(alpha) vpaint_blend(vp, mcol+3, mcolorig+3, vpd->paintcol, alpha); } } } @@ -1629,6 +1754,8 @@ static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) { + ToolSettings *ts= CTX_data_tool_settings(C); + VPaint *vp= ts->vpaint; struct VPaintData *vpd; Object *ob= CTX_data_active_object(C); Mesh *me; @@ -1647,10 +1774,10 @@ static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob); vpd->indexar= get_indexarray(); - vpd->paintcol= vpaint_get_current_col(&Gvp); + vpd->paintcol= vpaint_get_current_col(vp); /* for filtering */ - copy_vpaint_prev(&Gvp, (unsigned int *)me->mcol, me->totface); + copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface); /* some old cruft to sort out later */ Mat4MulMat4(mat, ob->obmat, vpd->vc.v3d->viewmat); @@ -1670,7 +1797,7 @@ void VIEW3D_OT_vpaint(wmOperatorType *ot) { /* identifiers */ - ot->name= "Vpaint"; + ot->name= "Vertex Paint"; ot->idname= "VIEW3D_OT_vpaint"; /* api callbacks */ diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index ed311e0ff0c..ae75c9d967b 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -58,6 +58,9 @@ void ED_editors_exit(bContext *C) /* frees all editmode undos */ undo_editmode_clear(); + /* global in meshtools... */ + mesh_octree_table(ob, NULL, NULL, 'e'); + if(ob) { if(ob->type==OB_MESH) { Mesh *me= ob->data; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1dfdd940cfa..ad280f46b26 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -374,7 +374,34 @@ typedef struct TransformOrientation { float mat[3][3]; } TransformOrientation; +typedef struct VPaint { + float r, g, b, a; + float size; /* of brush */ + float gamma, mul; + short mode, flag; + int tot, pad; /* allocation size of prev buffers */ + unsigned int *vpaint_prev; /* previous mesh colors */ + struct MDeformVert *wpaint_prev; /* previous vertex weights */ + + void *paintcursor; /* wm handle */ +} VPaint; + +/* VPaint flag */ +#define VP_COLINDEX 1 +#define VP_AREA 2 +#define VP_SOFT 4 +#define VP_NORMALS 8 +#define VP_SPRAY 16 +#define VP_MIRROR_X 32 +#define VP_HARD 64 +#define VP_ONLYVGROUP 128 + + + typedef struct ToolSettings { + VPaint *vpaint; /* vertex paint */ + VPaint *wpaint; /* weight paint */ + /* Subdivide Settings */ short cornertype; short editbutflag; |