Revision: 53260
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53260
Author:   campbellbarton
Date:     2012-12-22 08:19:27 +0000 (Sat, 22 Dec 2012)
Log Message:
-----------
Weight gradient tool for weight paint mode
- blends from current weight into alpha zero.
- uses brush alpha & curve.
- respects weight paint vertex/face select modes.
- updates realtime.


Access With
- Alt+LMB (linear gradient)
- Ctrl+Alt+LMB (radial gradient)


note:
- WM_gesture_straightline_* are used but not well suited to this task, may end 
up replacing with own modal operator.
- Key handling works but needs to be done better.

Modified Paths:
--------------
    trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py
    trunk/blender/source/blender/editors/sculpt_paint/paint_intern.h
    trunk/blender/source/blender/editors/sculpt_paint/paint_ops.c
    trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c
    trunk/blender/source/blender/windowmanager/intern/wm_operators.c

Modified: trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py 
2012-12-22 08:13:44 UTC (rev 53259)
+++ trunk/blender/release/scripts/startup/bl_ui/space_view3d_toolbar.py 
2012-12-22 08:19:27 UTC (rev 53260)
@@ -971,6 +971,7 @@
         col.operator("object.vertex_group_transfer_weight", text="Transfer 
Weights")
         col.operator("object.vertex_group_limit_total", text="Limit Total")
         col.operator("object.vertex_group_fix", text="Fix Deforms")
+        col.operator("paint.weight_gradient")
 
 
 class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_intern.h
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_intern.h    
2012-12-22 08:13:44 UTC (rev 53259)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_intern.h    
2012-12-22 08:19:27 UTC (rev 53260)
@@ -89,6 +89,12 @@
 void PAINT_OT_weight_sample(struct wmOperatorType *ot);
 void PAINT_OT_weight_sample_group(struct wmOperatorType *ot);
 
+enum {
+       WPAINT_GRADIENT_TYPE_LINEAR,
+       WPAINT_GRADIENT_TYPE_RADIAL
+};
+void PAINT_OT_weight_gradient(struct wmOperatorType *ot);
+
 void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot);
 void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
 

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_ops.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_ops.c       
2012-12-22 08:13:44 UTC (rev 53259)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_ops.c       
2012-12-22 08:19:27 UTC (rev 53260)
@@ -475,6 +475,7 @@
        WM_operatortype_append(PAINT_OT_weight_paint);
        WM_operatortype_append(PAINT_OT_weight_set);
        WM_operatortype_append(PAINT_OT_weight_from_bones);
+       WM_operatortype_append(PAINT_OT_weight_gradient);
        WM_operatortype_append(PAINT_OT_weight_sample);
        WM_operatortype_append(PAINT_OT_weight_sample_group);
 
@@ -710,6 +711,9 @@
        WM_keymap_verify_item(keymap, "PAINT_OT_weight_sample", LEFTMOUSE, 
KM_PRESS, KM_CTRL, 0);
        WM_keymap_verify_item(keymap, "PAINT_OT_weight_sample_group", 
LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
 
+       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_gradient", 
LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr,           "type", 
WPAINT_GRADIENT_TYPE_LINEAR);
+       RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_gradient", 
LEFTMOUSE, KM_PRESS, KM_ALT | KM_CTRL, 0)->ptr, "type", 
WPAINT_GRADIENT_TYPE_RADIAL);
+
        WM_keymap_add_item(keymap,
                           "PAINT_OT_weight_set", KKEY, KM_PRESS, KM_SHIFT, 0);
 

Modified: trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c
===================================================================
--- trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c    
2012-12-22 08:13:44 UTC (rev 53259)
+++ trunk/blender/source/blender/editors/sculpt_paint/paint_vertex.c    
2012-12-22 08:19:27 UTC (rev 53260)
@@ -2939,3 +2939,255 @@
        /* properties */
        ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", 
"Method to use for assigning weights");
 }
+
+/* *** VGroups Gradient *** */
+typedef struct DMGradient_vertStore {
+       float sco[2];
+       float weight_orig;
+       enum {
+               VGRAD_STORE_NOP      = 0,
+               VGRAD_STORE_DW_EXIST = (1 << 0)
+       } flag;
+} DMGradient_vertStore;
+
+typedef struct DMGradient_userData {
+       struct ARegion *ar;
+       Scene *scene;
+       Mesh *me;
+       Brush *brush;
+       const float *sco_start;     /* [2] */
+       const float *sco_end;       /* [2] */
+       float        sco_line_div;  /* store (1.0f / len_v2v2(sco_start, 
sco_end)) */
+       int def_nr;
+       short is_init;
+       DMGradient_vertStore *vert_cache;
+
+       /* options */
+       short use_select;
+       short type;
+       float weightpaint;
+} DMGradient_userData;
+
+static void gradientVert__mapFunc(void *userData, int index, const float co[3],
+                                  const float UNUSED(no_f[3]), const short 
UNUSED(no_s[3]))
+{
+       DMGradient_userData *grad_data = userData;
+       Mesh *me = grad_data->me;
+
+       if (grad_data->use_select == FALSE || (me->mvert[index].flag & SELECT)) 
{
+               DMGradient_vertStore *vs = &grad_data->vert_cache[index];
+
+               /* run first pass only, could be split into its own mapFunc
+                * the screen coords of the verts need to be cached because
+                * updating the mesh may move them about (entering feedback 
loop) */
+               if (grad_data->is_init) {
+                       if (ED_view3d_project_float_global(grad_data->ar,
+                                                          co, vs->sco,
+                                                          
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == 
V3D_PROJ_RET_OK)
+                       {
+                               /* ok */
+                               MDeformVert *dv = &me->dvert[index];
+                               MDeformWeight *dw;
+                               dw = defvert_find_index(dv, grad_data->def_nr);
+                               if (dw) {
+                                       vs->weight_orig = dw->weight;
+                                       vs->flag |= VGRAD_STORE_DW_EXIST;
+                               }
+                       }
+                       else {
+                               /* no go */
+                               copy_v2_fl(vs->sco, FLT_MAX);
+                       }
+               }
+               /* end init */
+
+               if (vs->sco[0] != FLT_MAX) {
+                       float alpha;
+
+                       if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
+                               alpha = line_point_factor_v2(vs->sco, 
grad_data->sco_start, grad_data->sco_end);
+                       }
+                       else if (grad_data->type == 
WPAINT_GRADIENT_TYPE_RADIAL) {
+                               alpha = len_v2v2(grad_data->sco_start, vs->sco) 
* grad_data->sco_line_div;
+                       }
+                       else {
+                               BLI_assert(0);
+                       }
+                       /* no need to clamp 'alpha' yet */
+
+                       /* adjust weight */
+                       alpha = 
BKE_brush_curve_strength_clamp(grad_data->brush, alpha, 1.0f);
+
+                       if (alpha != 0.0f) {
+                               MDeformVert *dv = &me->dvert[index];
+                               MDeformWeight *dw = defvert_verify_index(dv, 
grad_data->def_nr);
+                               // dw->weight = alpha; // testing
+                               int tool = grad_data->brush->vertexpaint_tool;
+                               float testw;
+
+                               /* init if we just added */
+                               testw = wpaint_blend_tool(tool, 
vs->weight_orig, grad_data->weightpaint, alpha * grad_data->brush->alpha);
+                               CLAMP(testw, 0.0f, 1.0f);
+                               dw->weight = testw;
+                       }
+                       else {
+                               MDeformVert *dv = &me->dvert[index];
+                               if (vs->flag & VGRAD_STORE_DW_EXIST) {
+                                       /* normally we NULL check, but in this 
case we know it exists */
+                                       MDeformWeight *dw = 
defvert_find_index(dv, grad_data->def_nr);
+                                       dw->weight = vs->weight_orig;
+                               }
+                               else {
+                                       /* wasn't originally existing, remove */
+                                       MDeformWeight *dw = 
defvert_find_index(dv, grad_data->def_nr);
+                                       if (dw) {
+                                               defvert_remove_group(dv, dw);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+static int paint_weight_gradient_modal(bContext *C, wmOperator *op, wmEvent 
*event)
+{
+       int ret = WM_gesture_straightline_modal(C, op, event);
+
+       if (ret & OPERATOR_RUNNING_MODAL) {
+               if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {  /* 
XXX, hardcoded */
+                       /* generally crap! redo! */
+                       WM_gesture_straightline_cancel(C, op);
+                       ret &= ~OPERATOR_RUNNING_MODAL;
+                       ret |= OPERATOR_FINISHED;
+               }
+       }
+
+       if (ret & OPERATOR_CANCELLED) {
+               ToolSettings *ts = CTX_data_tool_settings(C);
+               VPaint *wp = ts->wpaint;
+               Object *ob = CTX_data_active_object(C);
+               Mesh *me = ob->data;
+               copy_dverts(me->dvert, wp->wpaint_prev, me->totvert);
+               free_wpaint_prev(wp);
+
+               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+               WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+       }
+       else if (ret & OPERATOR_FINISHED) {
+               ToolSettings *ts = CTX_data_tool_settings(C);
+               VPaint *wp = ts->wpaint;
+               free_wpaint_prev(wp);
+       }
+
+       return ret;
+}
+
+static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
+{
+       wmGesture *gesture = op->customdata;
+       struct ARegion *ar = CTX_wm_region(C);
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
+       Mesh *me = ob->data;
+       int x_start = RNA_int_get(op->ptr, "xstart");
+       int y_start = RNA_int_get(op->ptr, "ystart");
+       int x_end = RNA_int_get(op->ptr, "xend");
+       int y_end = RNA_int_get(op->ptr, "yend");
+       float sco_start[2] = {x_start, y_start};
+       float sco_end[2] = {x_end, y_end};
+
+       DerivedMesh *dm = mesh_get_derived_final(scene, ob, 
scene->customdata_mask);
+
+       DMGradient_userData data = {0};
+
+       if (gesture->userdata == NULL) {
+               VPaint *wp = scene->toolsettings->wpaint;
+
+               gesture->userdata = MEM_mallocN(sizeof(DMGradient_vertStore) * 
me->totvert, __func__);
+               data.is_init = TRUE;
+
+               copy_wpaint_prev(wp, me->dvert, me->totvert);
+
+               /* on init only, convert face -> vert sel  */
+               if (me->editflag & ME_EDIT_PAINT_MASK) {
+                       BKE_mesh_flush_select_from_polys(me->mvert, me->totvert,
+                                                        me->mloop,
+                                                        me->medge, me->totedge,
+                                                        me->mpoly, 
me->totpoly);
+               }
+
+       }
+
+       data.ar = ar;
+       data.scene = scene;
+       data.me = ob->data;
+       data.sco_start = sco_start;
+       data.sco_end   = sco_end;
+       data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end);
+       data.def_nr = ob->actdef - 1;
+       data.use_select = (me->editflag & (ME_EDIT_PAINT_MASK | 
ME_EDIT_VERT_SEL));
+       data.vert_cache = gesture->userdata;
+       data.type = RNA_enum_get(op->ptr, "type");
+
+       {
+               ToolSettings *ts = CTX_data_tool_settings(C);
+               VPaint *wp = ts->wpaint;
+               struct Brush *brush = paint_brush(&wp->paint);
+               data.brush = brush;
+               data.weightpaint = BKE_brush_weight_get(scene, brush);
+       }
+
+       dm->foreachMappedVert(dm, gradientVert__mapFunc, &data);
+
+       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+       return OPERATOR_FINISHED;
+}
+
+static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, wmEvent 
*event)
+{
+       int ret = WM_gesture_straightline_invoke(C, op, event);
+       if (ret & OPERATOR_RUNNING_MODAL) {
+               struct ARegion *ar = CTX_wm_region(C);
+               if (ar->regiontype == RGN_TYPE_WINDOW) {
+                       if (event->type == LEFTMOUSE && event->val == KM_PRESS) 
{  /* TODO, hardcoded, extend WM_gesture_straightline_ */
+                               wmGesture *gesture = op->customdata;
+                               gesture->mode = 1;
+                       }
+               }
+       }
+       return ret;
+}
+
+void PAINT_OT_weight_gradient(wmOperatorType *ot)
+{
+       /* defined in DNA_space_types.h */
+       static EnumPropertyItem gradient_types[] = {
+               {WPAINT_GRADIENT_TYPE_LINEAR, "LINEAR", 0, "Linear", ""},
+               {WPAINT_GRADIENT_TYPE_RADIAL, "RADIAL", 0, "Radial", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       PropertyRNA *prop;
+
+       /* identifiers */
+       ot->name = "Weight Gradient";
+       ot->idname = "PAINT_OT_weight_gradient";

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to