Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/intern/brush.c52
-rw-r--r--source/blender/blenlib/BLI_math_vector.h2
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c12
-rw-r--r--source/blender/blenloader/intern/readfile.c13
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c115
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h6
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c179
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c22
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c2
-rw-r--r--source/blender/makesdna/DNA_brush_types.h3
-rw-r--r--source/blender/makesdna/DNA_texture_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_brush.c2
14 files changed, 368 insertions, 47 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 2d10b76378a..3e748550e7b 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 266
-#define BLENDER_SUBVERSION 4
+#define BLENDER_SUBVERSION 5
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 2f666bf5922..6dcd394c92a 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -121,6 +121,12 @@ static void brush_defaults(Brush *brush)
brush->sub_col[0] = 0.39; /* subtract mode color is light blue */
brush->sub_col[1] = 0.39;
brush->sub_col[2] = 1.00;
+
+ brush->stencil_pos[0] = 256;
+ brush->stencil_pos[1] = 256;
+
+ brush->stencil_dimension[0] = 256;
+ brush->stencil_dimension[1] = 256;
}
/* Datablock add/copy/free/make_local */
@@ -518,11 +524,45 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
hasrgb = externtex(mtex, point, &intensity,
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
+ else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) {
+ float rotation = -mtex->rot;
+ float point_2d[2] = {point[0], point[1]};
+ 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];
+
+ if (rotation > 0.001f || rotation < -0.001f) {
+ const float angle = atan2f(y, x) + rotation;
+ const float flen = sqrtf(x * x + y * y);
+
+ x = flen * cosf(angle);
+ y = flen * sinf(angle);
+ }
+
+ if (fabs(x) > br->stencil_dimension[0] || fabs(y) > br->stencil_dimension[1]) {
+ rgba[0] = rgba[1] = rgba[2] = rgba[3] = 0.0;
+ return 0.0;
+ }
+ x /= (br->stencil_dimension[0]);
+ y /= (br->stencil_dimension[1]);
+
+ x *= br->mtex.size[0];
+ y *= br->mtex.size[1];
+
+ co[0] = x + br->mtex.ofs[0];
+ co[1] = y + br->mtex.ofs[1];
+ co[2] = 0.0f;
+
+ hasrgb = externtex(mtex, co, &intensity,
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ }
else {
float rotation = -mtex->rot;
float point_2d[2] = {point[0], point[1]};
float x = 0.0f, y = 0.0f; /* Quite warnings */
- float radius = 1.0f; /* Quite warnings */
+ float invradius = 1.0f; /* Quite warnings */
float co[3];
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
@@ -534,13 +574,13 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
y = point_2d[1] - ups->tex_mouse[1];
/* use pressure adjusted size for fixed mode */
- radius = ups->pixel_radius;
+ invradius = 1.0/ups->pixel_radius;
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
/* leave the coordinates relative to the screen */
/* use unadjusted size for tiled mode */
- radius = BKE_brush_size_get(scene, br);
+ invradius = 1.0/BKE_brush_size_get(scene, br);
x = point_2d[0];
y = point_2d[1];
@@ -551,11 +591,11 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
x = point_2d[0] - ups->tex_mouse[0];
y = point_2d[1] - ups->tex_mouse[1];
- radius = ups->pixel_radius;
+ invradius = 1.0/ups->pixel_radius;
}
- x /= radius;
- y /= radius;
+ x *= invradius;
+ y *= invradius;
/* it is probably worth optimizing for those cases where
* the texture is not rotated by skipping the calls to
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index c9ad19f74b4..9cf571aa98b 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -92,6 +92,7 @@ MINLINE void add_v3_fl(float r[3], float f);
MINLINE void add_v4_fl(float r[4], float f);
MINLINE void add_v2_v2(float r[2], const float a[2]);
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2]);
+MINLINE void add_v2_v2v2_int(int r[2], const int a[2], const int b[2]);
MINLINE void add_v3_v3(float r[3], const float a[3]);
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void add_v4_v4(float r[4], const float a[4]);
@@ -99,6 +100,7 @@ MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4]);
MINLINE void sub_v2_v2(float r[2], const float a[2]);
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2]);
+MINLINE void sub_v2_v2v2_int(int r[2], const int a[2], const int b[2]);
MINLINE void sub_v3_v3(float r[3], const float a[3]);
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void sub_v4_v4(float r[4], const float a[4]);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index c8e8ff9602b..cce78b5e5d2 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -271,6 +271,12 @@ MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
r[1] = a[1] + b[1];
}
+MINLINE void add_v2_v2v2_int(int r[2], const int a[2], const int b[2])
+{
+ r[0] = a[0] + b[0];
+ r[1] = a[1] + b[1];
+}
+
MINLINE void add_v3_v3(float r[3], const float a[3])
{
r[0] += a[0];
@@ -313,6 +319,12 @@ MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
r[1] = a[1] - b[1];
}
+MINLINE void sub_v2_v2v2_int(int r[2], const int a[2], const int b[2])
+{
+ r[0] = a[0] - b[0];
+ r[1] = a[1] - b[1];
+}
+
MINLINE void sub_v3_v3(float r[3], const float a[3])
{
r[0] -= a[0];
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 682680e53c5..b605747c020 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -9077,7 +9077,18 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 267) {
-
+ //if(!DNA_struct_elem_find(fd->filesdna, "Brush", "int", "stencil_pos")) {
+ Brush *brush;
+
+ for (brush = main->brush.first; brush; brush = brush->id.next) {
+ if (brush->stencil_dimension[0] == 0) {
+ brush->stencil_dimension[0] = 256;
+ brush->stencil_dimension[1] = 256;
+ brush->stencil_pos[0] = 256;
+ brush->stencil_pos[1] = 256;
+ }
+ }
+
/* TIP: to initialize new variables added, use the new function
DNA_struct_elem_find(fd->filesdna, "structname", "typename", "varname")
example:
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 38660e371be..1616b3026bd 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -117,7 +117,7 @@ static void make_snap(Snapshot *snap, Brush *brush, ViewContext *vc)
snap->winy = vc->ar->winy;
}
-static int load_tex(Brush *br, ViewContext *vc, float zoom)
+static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
{
static GLuint overlay_texture = 0;
static int init = 0;
@@ -126,12 +126,14 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom)
static Snapshot snap;
static int old_size = -1;
static int old_zoom = -1;
+ static bool old_col = -1;
GLubyte *buffer = NULL;
int size;
int j;
int refresh;
+ int format = col? GL_RGBA : GL_ALPHA;
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED && !br->mtex.tex) return 0;
@@ -143,11 +145,15 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom)
!br->curve ||
br->curve->changed_timestamp != curve_changed_timestamp ||
old_zoom != zoom ||
+ old_col != col ||
!same_snap(&snap, br, vc);
if (refresh) {
struct ImagePool *pool = NULL;
- const float rotation = -br->mtex.rot;
+ /* stencil is rotated later */
+ const float rotation = (br->mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL)?
+ -br->mtex.rot : 0;
+
float radius = BKE_brush_size_get(vc->scene, br) * zoom;
if (br->mtex.tex && br->mtex.tex->preview)
@@ -187,8 +193,10 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom)
old_size = size;
}
-
- buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
+ if (col)
+ buffer = MEM_mallocN(sizeof(GLubyte) * size * size * 4, "load_tex");
+ else
+ buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
if (br->mtex.tex)
pool = BKE_image_pool_new();
@@ -205,7 +213,6 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom)
int index = j * size + i;
float x;
- float avg;
x = (float)i / size;
y = (float)j / size;
@@ -224,7 +231,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom)
len = sqrtf(x * x + y * y);
- if ((br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) || len <= 1) {
+ if (ELEM(br->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL) || len <= 1) {
/* it is probably worth optimizing for those cases where
* the texture is not rotated by skipping the calls to
* atan2, sqrtf, sin, and cos. */
@@ -241,17 +248,40 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom)
x += br->mtex.ofs[0];
y += br->mtex.ofs[1];
- avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y, pool) : 1;
+ if (col) {
+ float rgba[4];
- avg += br->texture_sample_bias;
+ if (br->mtex.tex)
+ paint_get_tex_pixel_col(&br->mtex, x, y, rgba, pool);
- if (br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW)
- avg *= BKE_brush_curve_strength(br, len, 1); /* Falloff curve */
+ if (br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW)
+ mul_v4_fl(rgba, BKE_brush_curve_strength(br, len, 1)); /* Falloff curve */
+
+ buffer[index*4] = rgba[0]*255;
+ buffer[index*4 + 1] = rgba[1]*255;
+ buffer[index*4 + 2] = rgba[2]*255;
+ buffer[index*4 + 3] = rgba[3]*255;
+ }
+ else {
+ float avg = br->mtex.tex ? paint_get_tex_pixel(&br->mtex, x, y, pool) : 1;
- buffer[index] = 255 - (GLubyte)(255 * avg);
+ avg += br->texture_sample_bias;
+
+ if (br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW)
+ avg *= BKE_brush_curve_strength(br, len, 1); /* Falloff curve */
+
+ buffer[index] = 255 - (GLubyte)(255 * avg);
+ }
}
else {
- buffer[index] = 0;
+ if (col) {
+ buffer[index*4] = 0;
+ buffer[index*4 + 1] = 0;
+ buffer[index*4 + 2] = 0;
+ buffer[index*4 + 3] = 0;
+ }
+ else
+ buffer[index] = 0;
}
}
}
@@ -269,16 +299,18 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom)
glBindTexture(GL_TEXTURE_2D, overlay_texture);
if (refresh) {
- if (!init) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
+ if (!init || (old_col != col)) {
+ glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
init = 1;
}
else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, format, GL_UNSIGNED_BYTE, buffer);
}
if (buffer)
MEM_freeN(buffer);
+
+ old_col = col;
}
glEnable(GL_TEXTURE_2D);
@@ -385,17 +417,21 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc,
* have on brush strength */
/* TODO: sculpt only for now */
static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
- ViewContext *vc, int x, int y, float zoom)
+ ViewContext *vc, int x, int y, float zoom, PaintMode mode)
{
rctf quad;
-
+ bool col;
/* check for overlay mode */
- if (!(brush->flag & BRUSH_TEXTURE_OVERLAY) ||
- !(ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED)))
+
+ if (brush->mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL &&
+ (!(brush->flag & BRUSH_TEXTURE_OVERLAY) ||
+ !ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED)))
{
return;
}
+ col = ELEM3(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX)?
+ true: false;
/* save lots of GL state
* TODO: check on whether all of these are needed? */
glPushAttrib(GL_COLOR_BUFFER_BIT |
@@ -409,7 +445,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
GL_VIEWPORT_BIT |
GL_TEXTURE_BIT);
- if (load_tex(brush, vc, zoom)) {
+ if (load_tex(brush, vc, zoom, col)) {
glEnable(GL_BLEND);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -449,18 +485,36 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
quad.ymax = y + radius;
}
}
- else {
+ else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_TILED){
quad.xmin = 0;
quad.ymin = 0;
quad.xmax = BLI_rcti_size_x(&vc->ar->winrct);
quad.ymax = BLI_rcti_size_y(&vc->ar->winrct);
}
+ else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL) {
+ quad.xmin = -brush->stencil_dimension[0];
+ quad.ymin = -brush->stencil_dimension[1];
+ quad.xmax = brush->stencil_dimension[0];
+ quad.ymax = brush->stencil_dimension[1];
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0);
+ glRotatef(brush->mtex.rot/M_PI*180, 0, 0, 1);
+ glMatrixMode(GL_TEXTURE);
+ }
- /* set quad color */
- glColor4f(U.sculpt_paint_overlay_col[0],
- U.sculpt_paint_overlay_col[1],
- U.sculpt_paint_overlay_col[2],
- brush->texture_overlay_alpha / 100.0f);
+ /* set quad color. Colored overlay does not get blending */
+ if (col)
+ glColor4f(1.0,
+ 1.0,
+ 1.0,
+ brush->texture_overlay_alpha / 100.0f);
+ else
+ glColor4f(U.sculpt_paint_overlay_col[0],
+ U.sculpt_paint_overlay_col[1],
+ U.sculpt_paint_overlay_col[2],
+ brush->texture_overlay_alpha / 100.0f);
/* draw textured quad */
glBegin(GL_QUADS);
@@ -475,6 +529,11 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glEnd();
glPopMatrix();
+
+ if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
}
glPopAttrib();
@@ -519,6 +578,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
Paint *paint = paint_get_active_from_context(C);
Brush *brush = paint_brush(paint);
ViewContext vc;
+ PaintMode mode;
float final_radius;
float translation[2];
float outline_alpha, *outline_col;
@@ -534,6 +594,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
get_imapaint_zoom(C, &zoomx, &zoomy);
zoomx = max_ff(zoomx, zoomy);
+ mode = paintmode_get_active_from_context(C);
/* set various defaults */
translation[0] = x;
@@ -549,7 +610,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
ups->brush_rotation = 0.0;
/* draw overlay */
- paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx);
+ paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
/* TODO: as sculpt and other paint modes are unified, this
* special mode of drawing will go away */
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index cfc40a826dd..8b1de32f1ea 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -39,6 +39,7 @@ struct Brush;
struct ImagePool;
struct ListBase;
struct Mesh;
+struct MTex;
struct Object;
struct PaintStroke;
struct Paint;
@@ -179,7 +180,8 @@ void paint_calc_redraw_planes(float planes[4][4],
void projectf(struct bglMats *mats, const float v[3], float p[2]);
float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius);
-float paint_get_tex_pixel(struct Brush *br, float u, float v, struct ImagePool *pool);
+float paint_get_tex_pixel(struct MTex *mtex, float u, float v, struct ImagePool *pool);
+void paint_get_tex_pixel_col(struct MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool);
int imapaint_pick_face(struct ViewContext *vc, const int mval[2], unsigned int *index, unsigned int totface);
void imapaint_pick_uv(struct Scene *scene, struct Object *ob, unsigned int faceindex, const int xy[2], float uv[2]);
void brush_drawcursor_texpaint_uvsculpt(struct bContext *C, int x, int y, void *customdata);
@@ -204,7 +206,7 @@ int facemask_paint_poll(struct bContext *C);
typedef enum BrushStrokeMode {
BRUSH_STROKE_NORMAL,
BRUSH_STROKE_INVERT,
- BRUSH_STROKE_SMOOTH,
+ BRUSH_STROKE_SMOOTH
} BrushStrokeMode;
/* paint_undo.c */
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 120d0a3b10a..7ea11cc464a 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -28,6 +28,7 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -307,11 +308,7 @@ static int brush_select_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
if (ob) {
/* select current paint mode */
- paint_mode = ob->mode &
- (OB_MODE_SCULPT |
- OB_MODE_VERTEX_PAINT |
- OB_MODE_WEIGHT_PAINT |
- OB_MODE_TEXTURE_PAINT);
+ paint_mode = ob->mode & OB_MODE_ALL_PAINT;
}
else {
return OPERATOR_CANCELLED;
@@ -448,6 +445,158 @@ static void BRUSH_OT_uv_sculpt_tool_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "tool", uv_sculpt_tool_items, 0, "Tool", "");
}
+/***** Stencil Control *****/
+
+enum {
+STENCIL_TRANSLATE,
+STENCIL_SCALE,
+STENCIL_ROTATE
+} StencilControlMode;
+
+typedef struct {
+ int init_mouse[2];
+ int init_spos[2];
+ int init_sdim[2];
+ float init_rot;
+ float init_angle;
+ float lenorig;
+ int mode;
+ Brush *br;
+} StencilControlData;
+
+static int stencil_control_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Paint *paint = paint_get_active_from_context(C);
+ Brush *br = paint->brush;
+ int mdiff[2];
+
+ StencilControlData *scd = MEM_mallocN(sizeof(StencilControlData), "stencil_control");
+
+ copy_v2_v2_int(scd->init_mouse, event->mval);
+ copy_v2_v2_int(scd->init_sdim, br->stencil_dimension);
+ copy_v2_v2_int(scd->init_spos, br->stencil_pos);
+ sub_v2_v2v2_int(mdiff, event->mval, br->stencil_pos);
+ scd->lenorig = sqrtf(mdiff[0]*mdiff[0] + mdiff[1]*mdiff[1]);
+ scd->br = br;
+ scd->init_rot = br->mtex.rot;
+ scd->init_angle = atan2(mdiff[1], mdiff[0]);
+ scd->mode = RNA_enum_get(op->ptr, "mode");
+
+ op->customdata = scd;
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+static int stencil_control_cancel(bContext *UNUSED(C), wmOperator *op)
+{
+ StencilControlData *scd = op->customdata;
+ Brush *br = scd->br;
+
+ copy_v2_v2_int(br->stencil_dimension, scd->init_sdim);
+ copy_v2_v2_int(br->stencil_pos, scd->init_spos);
+ br->mtex.rot = scd->init_rot;
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+}
+
+static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ StencilControlData *scd = op->customdata;
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ {
+ int mdiff[2];
+ switch (scd->mode) {
+ case STENCIL_TRANSLATE:
+ sub_v2_v2v2_int(mdiff, event->mval, scd->init_mouse);
+ add_v2_v2v2_int(scd->br->stencil_pos, scd->init_spos,
+ mdiff);
+ break;
+ case STENCIL_SCALE:
+ {
+ float len, factor;
+ sub_v2_v2v2_int(mdiff, event->mval, scd->br->stencil_pos);
+ len = sqrtf(mdiff[0]*mdiff[0] + mdiff[1]*mdiff[1]);
+ factor = len/scd->lenorig;
+ mdiff[0] = factor*scd->init_sdim[0];
+ mdiff[1] = factor*scd->init_sdim[1];
+ copy_v2_v2_int(scd->br->stencil_dimension, mdiff);
+ break;
+ }
+ case STENCIL_ROTATE:
+ {
+ float angle;
+ sub_v2_v2v2_int(mdiff, event->mval, scd->br->stencil_pos);
+ angle = atan2(mdiff[1], mdiff[0]);
+ angle = scd->init_rot + angle - scd->init_angle;
+ if (angle < 0)
+ angle += 2*M_PI;
+ if (angle > 2*M_PI)
+ angle -= 2*M_PI;
+ scd->br->mtex.rot = angle;
+ break;
+ }
+ }
+ }
+ break;
+ case LEFTMOUSE:
+ if(event->val == KM_PRESS) {
+ MEM_freeN(op->customdata);
+ return OPERATOR_FINISHED;
+ }
+ case RIGHTMOUSE:
+ if(event->val == KM_PRESS) {
+ return stencil_control_cancel(C, op);
+ }
+ default:
+ break;
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void BRUSH_OT_stencil_control(wmOperatorType *ot)
+{
+ static EnumPropertyItem stencil_control_items[] = {
+ {STENCIL_TRANSLATE, "TRANSLATION", 0, "Transation", ""},
+ {STENCIL_SCALE, "SCALE", 0, "Scale", ""},
+ {STENCIL_ROTATE, "ROTATION", 0, "Rotation", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ /* identifiers */
+ ot->name = "Stencil Brush Control";
+ ot->description = "Control the stencil brush";
+ ot->idname = "BRUSH_OT_stencil_control";
+
+ /* api callbacks */
+ ot->invoke = stencil_control_invoke;
+ ot->modal = stencil_control_modal;
+ ot->cancel = stencil_control_cancel;
+
+ /* flags */
+ ot->flag = 0;
+
+ RNA_def_enum(ot->srna, "mode", stencil_control_items, 0, "Tool", "");
+}
+
+static void ed_keymap_stencil(wmKeyMap *keymap)
+{
+ wmKeyMapItem *kmi;
+
+ kmi = WM_keymap_add_item(keymap, "BRUSH_OT_stencil_control", QKEY, KM_PRESS, 0, 0);
+ RNA_enum_set(kmi->ptr, "mode", STENCIL_TRANSLATE);
+ kmi = WM_keymap_add_item(keymap, "BRUSH_OT_stencil_control", QKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "mode", STENCIL_SCALE);
+ kmi = WM_keymap_add_item(keymap, "BRUSH_OT_stencil_control", QKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "mode", STENCIL_ROTATE);
+
+}
+
/**************************** registration **********************************/
void ED_operatortypes_paint(void)
@@ -457,6 +606,7 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(BRUSH_OT_scale_size);
WM_operatortype_append(BRUSH_OT_curve_preset);
WM_operatortype_append(BRUSH_OT_reset);
+ WM_operatortype_append(BRUSH_OT_stencil_control);
/* note, particle uses a different system, can be added with existing operators in wm.py */
WM_operatortype_append(PAINT_OT_brush_select);
@@ -671,6 +821,8 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_paint_brush_size(keymap, "tool_settings.sculpt.brush.size");
ed_keymap_paint_brush_radial_control(keymap, "sculpt", RC_ROTATION);
+ ed_keymap_stencil(keymap);
+
keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_DRAW, DKEY, 0);
keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_SMOOTH, SKEY, 0);
keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_PINCH, PKEY, 0);
@@ -687,7 +839,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
/* */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.stroke_method");
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.sculpt_stroke_method");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.use_smooth_stroke");
@@ -709,6 +861,8 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_paint_brush_size(keymap, "tool_settings.vertex_paint.brush.size");
ed_keymap_paint_brush_radial_control(keymap, "vertex_paint", RC_COLOR | RC_ROTATION);
+ ed_keymap_stencil(keymap);
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */
RNA_string_set(kmi->ptr, "data_path", "vertex_paint_object.data.use_paint_mask");
@@ -718,6 +872,9 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.texture_angle_source_random");
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
+
/* Weight Paint mode */
keymap = WM_keymap_find(keyconf, "Weight Paint", 0, 0);
keymap->poll = weight_paint_mode_poll;
@@ -738,6 +895,11 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_paint_brush_size(keymap, "tool_settings.weight_paint.brush.size");
ed_keymap_paint_brush_radial_control(keymap, "weight_paint", 0);
+ ed_keymap_stencil(keymap);
+
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* face mask toggle */
RNA_string_set(kmi->ptr, "data_path", "weight_paint_object.data.use_paint_mask");
@@ -776,6 +938,8 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_paint_brush_size(keymap, "tool_settings.image_paint.brush.size");
ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM | RC_ROTATION);
+ ed_keymap_stencil(keymap);
+
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */
RNA_string_set(kmi->ptr, "data_path", "image_paint_object.data.use_paint_mask");
@@ -785,6 +949,9 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.texture_angle_source_random");
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.stroke_method");
+
/* face-mask mode */
keymap = WM_keymap_find(keyconf, "Face Mask", 0, 0);
keymap->poll = facemask_paint_poll;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 1dadef1e0a4..47e20bcc5fb 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -59,6 +59,7 @@
#include "BIF_glutil.h"
#include "RE_shader_ext.h"
+#include "RE_render_ext.h"
#include "ED_view3d.h"
#include "ED_screen.h"
@@ -176,13 +177,13 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3],
return len_v3(delta) / scale;
}
-float paint_get_tex_pixel(Brush *br, float u, float v, struct ImagePool *pool)
+float paint_get_tex_pixel(MTex *mtex, float u, float v, struct ImagePool *pool)
{
TexResult texres = {0};
float co[3] = {u, v, 0.0f};
int hasrgb;
- hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres, pool);
+ hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, pool);
if (hasrgb & TEX_RGB)
texres.tin = rgb_to_grayscale(&texres.tr) * texres.ta;
@@ -190,6 +191,23 @@ float paint_get_tex_pixel(Brush *br, float u, float v, struct ImagePool *pool)
return texres.tin;
}
+void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool)
+{
+ float co[3] = {u, v, 0.0f};
+ int hasrgb;
+ float intensity;
+
+ hasrgb = externtex(mtex, co, &intensity,
+ rgba, rgba + 1, rgba + 2, rgba + 3, 0, pool);
+
+ if (!hasrgb) {
+ rgba[0] = intensity;
+ rgba[1] = intensity;
+ rgba[2] = intensity;
+ rgba[3] = 1.0f;
+ }
+}
+
/* 3D Paint */
static void imapaint_project(Object *ob, float model[4][4], float proj[4][4], const float co[3], float pco[4])
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 197231124fc..061f073b287 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -866,6 +866,7 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
{
float delta[2];
float dist_squared;
+ float factor = 1.0;
sub_v2_v2v2(delta, mval, co_ss);
dist_squared = dot_v2v2(delta, delta); /* len squared */
@@ -880,8 +881,9 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co
const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f}; /* we need a 3rd empty value */
BKE_brush_sample_tex_3D(vc->scene, brush, co_ss_3d, rgba, 0, NULL);
}
+ factor = rgba[3];
}
- return BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure);
+ return factor*BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure);
}
}
if (rgba)
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 5a6bc823dc0..9bb7760fcc0 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -968,7 +968,7 @@ static float tex_strength(SculptSession *ss, Brush *br,
x += br->mtex.ofs[0];
y += br->mtex.ofs[1];
- avg = paint_get_tex_pixel(br, x, y, ss->tex_pool);
+ avg = paint_get_tex_pixel(&br->mtex, x, y, ss->tex_pool);
avg += br->texture_sample_bias;
}
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 0c38adb3c83..29081f96867 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -105,6 +105,9 @@ typedef struct Brush {
float add_col[3];
float sub_col[3];
+
+ int stencil_pos[2];
+ int stencil_dimension[2];
} Brush;
/* Brush.flag */
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index afb2ac74d99..0b6e5f9c7bb 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -500,6 +500,7 @@ typedef struct ColorMapping {
#define MTEX_MAP_MODE_3D 2
#define MTEX_MAP_MODE_AREA 3
#define MTEX_MAP_MODE_RANDOM 4
+#define MTEX_MAP_MODE_STENCIL 5
/* **************** EnvMap ********************* */
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index a1e057aed69..fc46440d8cc 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -433,6 +433,7 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
{MTEX_MAP_MODE_TILED, "TILED", 0, "Tiled", ""},
{MTEX_MAP_MODE_3D, "3D", 0, "3D", ""},
{MTEX_MAP_MODE_RANDOM, "RANDOM", 0, "Random", ""},
+ {MTEX_MAP_MODE_STENCIL, "STENCIL", 0, "Stencil", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -441,6 +442,7 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
{MTEX_MAP_MODE_TILED, "TILED", 0, "Tiled", ""},
{MTEX_MAP_MODE_3D, "3D", 0, "3D", ""},
{MTEX_MAP_MODE_RANDOM, "RANDOM", 0, "Random", ""},
+ {MTEX_MAP_MODE_STENCIL, "STENCIL", 0, "Stencil", ""},
{0, NULL, 0, NULL, NULL}
};