From 157244b13cf61d5889f5714167c6e5468ae35b15 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Tue, 23 Apr 2013 00:06:22 +0000 Subject: Add stencil control for mask overlay. Key combinations are the same as 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 | 10 +- source/blender/blenloader/intern/readfile.c | 6 + source/blender/editors/sculpt_paint/paint_cursor.c | 22 +++- source/blender/editors/sculpt_paint/paint_ops.c | 132 ++++++++++++++++----- source/blender/makesdna/DNA_brush_types.h | 3 + source/blender/makesrna/intern/rna_brush.c | 12 ++ 6 files changed, 143 insertions(+), 42 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 064e902f831..e52d1d3b683 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -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]; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 806ca280789..466c0b6dcb2 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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 diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 49863621b04..2f49433d5bb 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -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); } diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index ae49fbcbc95..f0265fd4e69 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -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 **********************************/ diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 2ed6b29caec..c37758fb940 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -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 */ diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 8e6bb976283..66a5ed947d7 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -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); -- cgit v1.2.3