Add stencil control for mask overlay. Key combinations are the same as
authorAntony Riakiotakis <kalast@gmail.com>
Tue, 23 Apr 2013 00:06:22 +0000 (00:06 +0000)
committerAntony Riakiotakis <kalast@gmail.com>
Tue, 23 Apr 2013 00:06:22 +0000 (00:06 +0000)
regular stencil but use Alt as well, so Alt-Rclick is translation, Alt-
clamping to avoid scaling of stencil to zero.

source/blender/blenkernel/intern/brush.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/sculpt_paint/paint_cursor.c
source/blender/editors/sculpt_paint/paint_ops.c
source/blender/makesdna/DNA_brush_types.h
source/blender/makesrna/intern/rna_brush.c

index 064e902f83134e75f423dd0bb7383eddeb26590c..e52d1d3b6833b269556578800623c3be699c9707 100644 (file)
@@ -661,8 +661,8 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
                float x = 0.0f, y = 0.0f; /* Quite warnings */
                float co[3];
 
-               x = point_2d[0] - br->stencil_pos[0];
-               y = point_2d[1] - br->stencil_pos[1];
+               x = point_2d[0] - br->mask_stencil_pos[0];
+               y = point_2d[1] - br->mask_stencil_pos[1];
 
                if (rotation > 0.001f || rotation < -0.001f) {
                        const float angle    = atan2f(y, x) + rotation;
@@ -672,12 +672,12 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
                        y = flen * sinf(angle);
                }
 
-               if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) {
+               if (fabsf(x) > br->mask_stencil_dimension[0] || fabsf(y) > br->mask_stencil_dimension[1]) {
                        zero_v4(rgba);
                        return 0.0f;
                }
-               x /= (br->stencil_dimension[0]);
-               y /= (br->stencil_dimension[1]);
+               x /= (br->mask_stencil_dimension[0]);
+               y /= (br->mask_stencil_dimension[1]);
 
                x *= mtex->size[0];
                y *= mtex->size[1];
index 806ca2807895f04e6e9abafceb54e65fafa4e6c9..466c0b6dcb2720a5f22421edc8b00bafb7369e81 100644 (file)
@@ -9318,6 +9318,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                brush->stencil_pos[0] = 256;
                                brush->stencil_pos[1] = 256;
                        }
+                       if (brush->mask_stencil_dimension[0] == 0) {
+                               brush->mask_stencil_dimension[0] = 256;
+                               brush->mask_stencil_dimension[1] = 256;
+                               brush->mask_stencil_pos[0] = 256;
+                               brush->mask_stencil_pos[1] = 256;
+                       }
                }
 
                /* TIP: to initialize new variables added, use the new function
index 49863621b044ce4b250610bb8ac3c7ef27c499b5..2f49433d5bb6d71afe3e4365841c90a3df745aab 100644 (file)
@@ -585,14 +585,24 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
                }
                /* Stencil code goes here */
                else {
-                       quad.xmin = -brush->stencil_dimension[0];
-                       quad.ymin = -brush->stencil_dimension[1];
-                       quad.xmax = brush->stencil_dimension[0];
-                       quad.ymax = brush->stencil_dimension[1];
-
+                       if (primary) {
+                               quad.xmin = -brush->stencil_dimension[0];
+                               quad.ymin = -brush->stencil_dimension[1];
+                               quad.xmax = brush->stencil_dimension[0];
+                               quad.ymax = brush->stencil_dimension[1];
+                       }
+                       else {
+                               quad.xmin = -brush->mask_stencil_dimension[0];
+                               quad.ymin = -brush->mask_stencil_dimension[1];
+                               quad.xmax = brush->mask_stencil_dimension[0];
+                               quad.ymax = brush->mask_stencil_dimension[1];
+                       }
                        glMatrixMode(GL_MODELVIEW);
                        glPushMatrix();
-                       glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0);
+                       if (primary)
+                               glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0);
+                       else
+                               glTranslatef(brush->mask_stencil_pos[0], brush->mask_stencil_pos[1], 0);
                        glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1);
                        glMatrixMode(GL_TEXTURE);
                }
index ae49fbcbc951fdbc1a586d15297dc9539471dda8..f0265fd4e690c7873902fb43ec2740b09f7d908b 100644 (file)
@@ -451,14 +451,20 @@ static void BRUSH_OT_uv_sculpt_tool_set(wmOperatorType *ot)
 /***** Stencil Control *****/
 
 typedef enum {
-STENCIL_TRANSLATE,
-STENCIL_SCALE,
-STENCIL_ROTATE
+       STENCIL_TRANSLATE,
+       STENCIL_SCALE,
+       STENCIL_ROTATE
 } StencilControlMode;
 
 typedef enum {
-STENCIL_CONSTRAINT_X = 1,
-STENCIL_CONSTRAINT_Y = 2
+       STENCIL_PRIMARY = 0,
+       STENCIL_SECONDARY = 1
+} StencilTextureMode;
+
+
+typedef enum {
+       STENCIL_CONSTRAINT_X = 1,
+       STENCIL_CONSTRAINT_Y = 2
 } StencilConstraint;
 
 typedef struct {
@@ -471,48 +477,92 @@ typedef struct {
        float area_size[2];
        StencilControlMode mode;
        StencilConstraint constrain_mode;
+       int mask; /* we are twaking mask or colour stencil */
        Brush *br;
+       float *dim_target;
+       float *rot_target;
+       float *pos_target;
        short event_type;
 } StencilControlData;
 
+static void stencil_set_target(StencilControlData *scd)
+{
+       Brush *br = scd->br;
+       float mdiff[2];
+       if (scd->mask) {
+               copy_v2_v2(scd->init_sdim, br->mask_stencil_dimension);
+               copy_v2_v2(scd->init_spos, br->mask_stencil_pos);
+               scd->init_rot = br->mask_mtex.rot;
+
+               scd->dim_target = br->mask_stencil_dimension;
+               scd->rot_target = &br->mask_mtex.rot;
+               scd->pos_target = br->mask_stencil_pos;
+       } else {
+               copy_v2_v2(scd->init_sdim, br->stencil_dimension);
+               copy_v2_v2(scd->init_spos, br->stencil_pos);
+               scd->init_rot = br->mtex.rot;
+
+               scd->dim_target = br->stencil_dimension;
+               scd->rot_target = &br->mtex.rot;
+               scd->pos_target = br->stencil_pos;
+       }
+
+       sub_v2_v2v2(mdiff, scd->init_mouse, br->stencil_pos);
+       scd->lenorig = len_v2(mdiff);
+
+       scd->init_angle = atan2(mdiff[1], mdiff[0]);
+}
+
 static int stencil_control_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 {
        Paint *paint = BKE_paint_get_active_from_context(C);
        Brush *br = BKE_paint_brush(paint);
-       float mdiff[2];
        float mvalf[2] = {event->mval[0], event->mval[1]};
        ARegion *ar = CTX_wm_region(C);
+       StencilControlData *scd;
+       int mask = RNA_enum_get(op->ptr, "texmode");
+
+       if (mask) {
+               if (br->mask_mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL)
+                       return OPERATOR_CANCELLED;
+       }
+       else {
+               if (br->mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL)
+                       return OPERATOR_CANCELLED;
+       }
 
-       StencilControlData *scd = MEM_mallocN(sizeof(StencilControlData), "stencil_control");
+       scd = MEM_mallocN(sizeof(StencilControlData), "stencil_control");
+       scd->mask = mask;
+       scd->br = br;
 
        copy_v2_v2(scd->init_mouse, mvalf);
-       copy_v2_v2(scd->init_sdim, br->stencil_dimension);
-       copy_v2_v2(scd->init_spos, br->stencil_pos);
-       sub_v2_v2v2(mdiff, mvalf, br->stencil_pos);
-       scd->lenorig = len_v2(mdiff);
-       scd->br = br;
-       scd->init_rot = br->mtex.rot;
-       scd->init_angle = atan2(mdiff[1], mdiff[0]);
+
+       stencil_set_target(scd);
+
        scd->mode = RNA_enum_get(op->ptr, "mode");
        scd->event_type = event->type;
        scd->area_size[0] = ar->winx;
        scd->area_size[1] = ar->winy;
 
+
        op->customdata = scd;
        WM_event_add_modal_handler(C, op);
 
        return OPERATOR_RUNNING_MODAL;
 }
 
+static void stencil_restore(StencilControlData *scd)
+{
+       copy_v2_v2(scd->dim_target, scd->init_sdim);
+       copy_v2_v2(scd->pos_target, scd->init_spos);
+       *scd->rot_target = scd->init_rot;
+}
 
 static int stencil_control_cancel(bContext *UNUSED(C), wmOperator *op)
 {
        StencilControlData *scd = op->customdata;
-       Brush *br = scd->br;
 
-       copy_v2_v2(br->stencil_dimension, scd->init_sdim);
-       copy_v2_v2(br->stencil_pos, scd->init_spos);
-       br->mtex.rot = scd->init_rot;
+       stencil_restore(scd);
        MEM_freeN(op->customdata);
        return OPERATOR_CANCELLED;
 }
@@ -526,21 +576,21 @@ static void stencil_control_calculate(StencilControlData *scd, const int mval[2]
        switch (scd->mode) {
                case STENCIL_TRANSLATE:
                        sub_v2_v2v2(mdiff, mvalf, scd->init_mouse);
-                       add_v2_v2v2(scd->br->stencil_pos, scd->init_spos,
+                       add_v2_v2v2(scd->pos_target, scd->init_spos,
                                    mdiff);
-                       CLAMP(scd->br->stencil_pos[0],
-                             -scd->br->stencil_dimension[0] + PIXEL_MARGIN,
-                             scd->area_size[0] + scd->br->stencil_dimension[0] - PIXEL_MARGIN);
+                       CLAMP(scd->pos_target[0],
+                             -scd->dim_target[0] + PIXEL_MARGIN,
+                             scd->area_size[0] + scd->dim_target[0] - PIXEL_MARGIN);
 
-                       CLAMP(scd->br->stencil_pos[1],
-                             -scd->br->stencil_dimension[1] + PIXEL_MARGIN,
-                             scd->area_size[1] + scd->br->stencil_dimension[1] - PIXEL_MARGIN);
+                       CLAMP(scd->pos_target[1],
+                             -scd->dim_target[1] + PIXEL_MARGIN,
+                             scd->area_size[1] + scd->dim_target[1] - PIXEL_MARGIN);
 
                        break;
                case STENCIL_SCALE:
                {
                        float len, factor;
-                       sub_v2_v2v2(mdiff, mvalf, scd->br->stencil_pos);
+                       sub_v2_v2v2(mdiff, mvalf, scd->pos_target);
                        len = len_v2(mdiff);
                        factor = len / scd->lenorig;
                        copy_v2_v2(mdiff, scd->init_sdim);
@@ -548,20 +598,22 @@ static void stencil_control_calculate(StencilControlData *scd, const int mval[2]
                                mdiff[0] = factor * scd->init_sdim[0];
                        if (scd->constrain_mode != STENCIL_CONSTRAINT_X)
                                mdiff[1] = factor * scd->init_sdim[1];
-                       copy_v2_v2(scd->br->stencil_dimension, mdiff);
+                       CLAMP(mdiff[0], 5.0, 10000);
+                       CLAMP(mdiff[1], 5.0, 10000);
+                       copy_v2_v2(scd->dim_target, mdiff);
                        break;
                }
                case STENCIL_ROTATE:
                {
                        float angle;
-                       sub_v2_v2v2(mdiff, mvalf, scd->br->stencil_pos);
+                       sub_v2_v2v2(mdiff, mvalf, scd->pos_target);
                        angle = atan2(mdiff[1], mdiff[0]);
                        angle = scd->init_rot + angle - scd->init_angle;
                        if (angle < 0.0f)
                                angle += (float)(2 * M_PI);
                        if (angle > (float)(2 * M_PI))
                                angle -= (float)(2 * M_PI);
-                       scd->br->mtex.rot = angle;
+                       *scd->rot_target = angle;
                        break;
                }
        }
@@ -623,7 +675,9 @@ static int stencil_control_poll(bContext *C)
        Paint *paint = BKE_paint_get_active_from_context(C);
        Brush *br = BKE_paint_brush(paint);
 
-       return (br && br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL);
+       return (br &&
+                       (br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL ||
+                        br->mask_mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL));
 }
 
 static void BRUSH_OT_stencil_control(wmOperatorType *ot)
@@ -634,6 +688,12 @@ static void BRUSH_OT_stencil_control(wmOperatorType *ot)
                {STENCIL_ROTATE, "ROTATION", 0, "Rotation", ""},
                {0, NULL, 0, NULL, NULL}
        };
+
+       static EnumPropertyItem stencil_texture_items[] = {
+               {STENCIL_PRIMARY, "PRIMARY", 0, "Primary", ""},
+               {STENCIL_SECONDARY, "SECONDARY", 0, "Secondary", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
        /* identifiers */
        ot->name = "Stencil Brush Control";
        ot->description = "Control the stencil brush";
@@ -648,7 +708,8 @@ static void BRUSH_OT_stencil_control(wmOperatorType *ot)
        /* flags */
        ot->flag = 0;
 
-       RNA_def_enum(ot->srna, "mode", stencil_control_items, 0, "Tool", "");
+       RNA_def_enum(ot->srna, "mode", stencil_control_items, STENCIL_TRANSLATE, "Tool", "");
+       RNA_def_enum(ot->srna, "texmode", stencil_texture_items, STENCIL_PRIMARY, "Tool", "");
 }
 
 
@@ -721,6 +782,15 @@ static void ed_keymap_stencil(wmKeyMap *keymap)
        kmi = WM_keymap_add_item(keymap, "BRUSH_OT_stencil_control", RIGHTMOUSE, KM_PRESS, KM_CTRL, 0);
        RNA_enum_set(kmi->ptr, "mode", STENCIL_ROTATE);
 
+       kmi = WM_keymap_add_item(keymap, "BRUSH_OT_stencil_control", RIGHTMOUSE, KM_PRESS, KM_ALT, 0);
+       RNA_enum_set(kmi->ptr, "mode", STENCIL_TRANSLATE);
+       RNA_enum_set(kmi->ptr, "texmode", STENCIL_SECONDARY);
+       kmi = WM_keymap_add_item(keymap, "BRUSH_OT_stencil_control", RIGHTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0);
+       RNA_enum_set(kmi->ptr, "texmode", STENCIL_SECONDARY);
+       RNA_enum_set(kmi->ptr, "mode", STENCIL_SCALE);
+       kmi = WM_keymap_add_item(keymap, "BRUSH_OT_stencil_control", RIGHTMOUSE, KM_PRESS, KM_CTRL | KM_ALT, 0);
+       RNA_enum_set(kmi->ptr, "texmode", STENCIL_SECONDARY);
+       RNA_enum_set(kmi->ptr, "mode", STENCIL_ROTATE);
 }
 
 /**************************** registration **********************************/
index 2ed6b29caec4fc9b47992926abc68eae78952d70..c37758fb940fd7da35f34a27ce000fb03b3abee9 100644 (file)
@@ -111,6 +111,9 @@ typedef struct Brush {
 
        float stencil_pos[2];
        float stencil_dimension[2];
+
+       float mask_stencil_pos[2];
+       float mask_stencil_dimension[2];
 } Brush;
 
 /* Brush.flag */
index 8e6bb97628309ff3330e6c913eb83cec6a9f17d6..66a5ed947d72da294c0bc3ca6e7a8e1d6f7de177 100644 (file)
@@ -855,6 +855,18 @@ static void rna_def_brush(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Stencil Dimensions", "Dimensions of stencil in viewport");
        RNA_def_property_update(prop, 0, "rna_Brush_update");
 
+       prop = RNA_def_property(srna, "mask_stencil_pos", PROP_FLOAT, PROP_XYZ);
+       RNA_def_property_float_sdna(prop, NULL, "mask_stencil_pos");
+       RNA_def_property_array(prop, 2);
+       RNA_def_property_ui_text(prop, "Mask Stencil Position", "Position of mask stencil in viewport");
+       RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+       prop = RNA_def_property(srna, "mask_stencil_dimension", PROP_FLOAT, PROP_XYZ);
+       RNA_def_property_float_sdna(prop, NULL, "mask_stencil_dimension");
+       RNA_def_property_array(prop, 2);
+       RNA_def_property_ui_text(prop, "Mask Stencil Dimensions", "Dimensions of mask stencil in viewport");
+       RNA_def_property_update(prop, 0, "rna_Brush_update");
+
        /* flag */
        prop = RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH);