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:
authorAntony Riakiotakis <kalast@gmail.com>2013-04-23 00:46:18 +0400
committerAntony Riakiotakis <kalast@gmail.com>2013-04-23 00:46:18 +0400
commit36e476ede6dae4cc21e1d9a05b7e9b93d52f70d1 (patch)
tree2275ccfce9f899f26243915e7d602caf40b36ca4 /source/blender
parent3c67cf9594264d8c4fc44f8f15e4033aa9b0e92d (diff)
Overlay refactor:
Allow separate control for tex/mask/cursor overlay. This commit implements separate overlays for mask textures and cursor curves. The user can turn on and off separate parts of the overlay by using the appropriate widgets. The cursor overlay widgets are located at the tool selection panel Also fixed alpha masks not getting correctly masked and mask texture mapping not having the correct update callback
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/intern/paint.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c391
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c6
-rw-r--r--source/blender/makesrna/intern/rna_brush.c2
5 files changed, 310 insertions, 97 deletions
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index ff5efd3b02b..5b53f1d34c9 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -79,7 +79,7 @@ void BKE_paint_invalidate_overlay_tex(struct Scene *scene, const struct Tex *tex
void BKE_paint_invalidate_cursor_overlay(struct Scene *scene, struct CurveMapping *curve);
void BKE_paint_invalidate_overlay_all(void);
OverlayControlFlags BKE_paint_get_overlay_flags(void);
-void BKE_paint_reset_overlay_invalid(void);
+void BKE_paint_reset_overlay_invalid(OverlayControlFlags flag);
void BKE_paint_set_overlay_override(bool flag);
bool BKE_paint_get_overlay_override(void);
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 59bfb987a19..ef751d130db 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -108,11 +108,9 @@ bool BKE_paint_get_overlay_override(void)
}
-void BKE_paint_reset_overlay_invalid(void)
+void BKE_paint_reset_overlay_invalid(OverlayControlFlags flag)
{
- overlay_flags &= ~(PAINT_INVALID_OVERLAY_TEXTURE_PRIMARY |
- PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY |
- PAINT_INVALID_OVERLAY_CURVE);
+ overlay_flags &= ~(flag);
}
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 7525085fd53..3770ff7b85d 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -69,9 +69,13 @@
*/
typedef struct TexSnapshot {
+ GLuint overlay_texture;
int winx;
int winy;
bool init;
+ int old_size;
+ int old_zoom;
+ bool old_col;
} TexSnapshot;
typedef struct CurveSnapshot {
@@ -80,35 +84,35 @@ typedef struct CurveSnapshot {
bool init;
} CurveSnapshot;
-static int same_tex_snap(TexSnapshot *snap, Brush *brush, ViewContext *vc)
+static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool col, float zoom)
{
- MTex *mtex = &brush->mtex;
-
return (/* make brush smaller shouldn't cause a resample */
//(mtex->brush_map_mode != MTEX_MAP_MODE_VIEW ||
//(BKE_brush_size_get(vc->scene, brush) <= snap->BKE_brush_size_get)) &&
(mtex->brush_map_mode != MTEX_MAP_MODE_TILED ||
(vc->ar->winx == snap->winx &&
- vc->ar->winy == snap->winy))
+ vc->ar->winy == snap->winy)) &&
+ snap->old_zoom == zoom &&
+ snap->old_col == col
);
}
-static void make_tex_snap(TexSnapshot *snap, ViewContext *vc)
+static void make_tex_snap(TexSnapshot *snap, ViewContext *vc, float zoom)
{
+ snap->old_zoom = zoom;
snap->winx = vc->ar->winx;
snap->winy = vc->ar->winy;
}
-static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
+static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool primary)
{
- static GLuint overlay_texture = 0;
static int init = 0;
- static TexSnapshot snap;
- static int old_size = -1;
- static int old_zoom = -1;
- static bool old_col = -1;
+ static TexSnapshot primary_snap = {0};
+ static TexSnapshot secondary_snap = {0};
+ TexSnapshot *target;
+ MTex *mtex = (primary) ? &br->mtex : &br->mask_mtex;
OverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags();
GLubyte *buffer = NULL;
@@ -116,29 +120,29 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
int j;
int refresh;
GLenum format = col ? GL_RGBA : GL_ALPHA;
+ OverlayControlFlags invalid = (primary) ? (overlay_flags & PAINT_INVALID_OVERLAY_TEXTURE_PRIMARY) :
+ (overlay_flags & PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY);
+
+ target = (primary) ? &primary_snap : &secondary_snap;
- if (br->mtex.brush_map_mode != MTEX_MAP_MODE_VIEW && !br->mtex.tex) return 0;
+ if (mtex->brush_map_mode != MTEX_MAP_MODE_VIEW && !mtex->tex) return 0;
refresh =
- !overlay_texture ||
- (overlay_flags & PAINT_INVALID_OVERLAY_TEXTURE_PRIMARY) ||
- (overlay_flags & PAINT_INVALID_OVERLAY_CURVE) ||
- old_zoom != zoom ||
- old_col != col ||
- !same_tex_snap(&snap, br, vc);
+ !target->overlay_texture ||
+ (invalid != 0) ||
+ !same_tex_snap(target, mtex, vc, col, zoom);
if (refresh) {
struct ImagePool *pool = NULL;
/* stencil is rotated later */
- const float rotation = (br->mtex.brush_map_mode != MTEX_MAP_MODE_STENCIL) ?
- -br->mtex.rot : 0;
+ const float rotation = (mtex->brush_map_mode != MTEX_MAP_MODE_STENCIL) ?
+ -mtex->rot : 0;
float radius = BKE_brush_size_get(vc->scene, br) * zoom;
- old_zoom = zoom;
- make_tex_snap(&snap, vc);
+ make_tex_snap(target, vc, zoom);
- if (br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
int s = BKE_brush_size_get(vc->scene, br);
int r = 1;
@@ -150,32 +154,30 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
if (size < 256)
size = 256;
- if (size < old_size)
- size = old_size;
+ if (size < target->old_size)
+ size = target->old_size;
}
else
size = 512;
- if (old_size != size) {
- if (overlay_texture) {
- glDeleteTextures(1, &overlay_texture);
- overlay_texture = 0;
+ if (target->old_size != size) {
+ if (target->overlay_texture) {
+ glDeleteTextures(1, &target->overlay_texture);
+ target->overlay_texture = 0;
}
init = 0;
- old_size = size;
+ target->old_size = size;
}
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)
+ if (mtex->tex)
pool = BKE_image_pool_new();
- curvemapping_initialize(br->curve);
-
#pragma omp parallel for schedule(static)
for (j = 0; j < size; j++) {
int i;
@@ -192,7 +194,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
x = (float)i / size;
y = (float)j / size;
- if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) {
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
x *= vc->ar->winx / radius;
y *= vc->ar->winy / radius;
}
@@ -206,47 +208,39 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
len = sqrtf(x * x + y * y);
- if (ELEM(br->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL) || len <= 1) {
+ if (ELEM(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. */
- if (br->mtex.tex && (rotation > 0.001f || rotation < -0.001f)) {
- const float angle = atan2f(y, x) + rotation;
+ if (mtex->tex && (rotation > 0.001f || rotation < -0.001f)) {
+ const float angle = atan2f(y, x) + rotation;
x = len * cosf(angle);
y = len * sinf(angle);
}
- x *= br->mtex.size[0];
- y *= br->mtex.size[1];
+ x *= mtex->size[0];
+ y *= mtex->size[1];
- x += br->mtex.ofs[0];
- y += br->mtex.ofs[1];
+ x += mtex->ofs[0];
+ y += mtex->ofs[1];
if (col) {
float rgba[4];
- if (br->mtex.tex)
- paint_get_tex_pixel_col(&br->mtex, x, y, rgba, pool);
+ if (mtex->tex)
+ paint_get_tex_pixel_col(mtex, x, y, rgba, pool);
- if (br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- float curve_str = BKE_brush_curve_strength(br, len, 1.0f);
- CLAMP(curve_str, 0.0f, 1.0f);
- mul_v4_fl(rgba, curve_str); /* 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;
+ float avg = mtex->tex ? paint_get_tex_pixel(mtex, x, y, pool) : 1;
avg += br->texture_sample_bias;
- if (br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW)
- avg *= BKE_brush_curve_strength(br, len, 1.0f); /* Falloff curve */
-
/* clamp to avoid precision overflow */
CLAMP(avg, 0.0f, 1.0f);
buffer[index] = 255 - (GLubyte)(255 * avg);
@@ -269,17 +263,17 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
if (pool)
BKE_image_pool_free(pool);
- if (!overlay_texture)
- glGenTextures(1, &overlay_texture);
+ if (!target->overlay_texture)
+ glGenTextures(1, &target->overlay_texture);
}
else {
- size = old_size;
+ size = target->old_size;
}
- glBindTexture(GL_TEXTURE_2D, overlay_texture);
+ glBindTexture(GL_TEXTURE_2D, target->overlay_texture);
if (refresh) {
- if (!init || (old_col != col)) {
+ if (!init || (target->old_col != col)) {
glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, format, GL_UNSIGNED_BYTE, buffer);
init = 1;
}
@@ -290,7 +284,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
if (buffer)
MEM_freeN(buffer);
- old_col = col;
+ target->old_col = col;
}
glEnable(GL_TEXTURE_2D);
@@ -299,16 +293,154 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- if (br->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
}
- BKE_paint_reset_overlay_invalid();
+ BKE_paint_reset_overlay_invalid(invalid);
+
+ return 1;
+}
+
+static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom)
+{
+ static GLuint overlay_texture = 0;
+ static int init = 0;
+ static int old_size = -1;
+ static int old_zoom = -1;
+
+ OverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags();
+ GLubyte *buffer = NULL;
+
+ int size;
+ int j;
+ int refresh;
+
+ if (br->mtex.brush_map_mode != MTEX_MAP_MODE_VIEW && !br->mtex.tex) return 0;
+
+ refresh =
+ !overlay_texture ||
+ (overlay_flags & PAINT_INVALID_OVERLAY_CURVE) ||
+ old_zoom != zoom;
+
+ if (refresh) {
+ int s, r;
+ float radius;
+
+ old_zoom = zoom;
+
+ s = BKE_brush_size_get(vc->scene, br);
+ r = 1;
+ radius = s * zoom;
+
+ for (s >>= 1; s > 0; s >>= 1)
+ r++;
+
+ size = (1 << r);
+
+ if (size < 256)
+ size = 256;
+
+ if (size < old_size)
+ size = old_size;
+
+ if (old_size != size) {
+ if (overlay_texture) {
+ glDeleteTextures(1, &overlay_texture);
+ overlay_texture = 0;
+ }
+
+ init = 0;
+
+ old_size = size;
+ }
+ buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
+
+ curvemapping_initialize(br->curve);
+
+ #pragma omp parallel for schedule(static)
+ for (j = 0; j < size; j++) {
+ int i;
+ float y;
+ float len;
+
+ for (i = 0; i < size; i++) {
+
+ // largely duplicated from tex_strength
+
+ int index = j * size + i;
+ float x;
+
+ x = (float)i / size;
+ y = (float)j / size;
+
+ if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) {
+ x *= vc->ar->winx / radius;
+ y *= vc->ar->winy / radius;
+ }
+ else {
+ x -= 0.5f;
+ y -= 0.5f;
+
+ x *= 2;
+ y *= 2;
+ }
+
+ len = sqrtf(x * x + y * y);
+
+ if (len <= 1) {
+ float avg = BKE_brush_curve_strength(br, len, 1.0f); /* Falloff curve */
+
+ /* clamp to avoid precision overflow */
+ CLAMP(avg, 0.0f, 1.0f);
+ buffer[index] = 255 - (GLubyte)(255 * avg);
+
+ }
+ else {
+ buffer[index] = 0;
+ }
+ }
+ }
+
+ if (!overlay_texture)
+ glGenTextures(1, &overlay_texture);
+ }
+ else {
+ size = old_size;
+ }
+
+ 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);
+ init = 1;
+ }
+ else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
+ }
+
+ if (buffer)
+ MEM_freeN(buffer);
+ }
+
+ glEnable(GL_TEXTURE_2D);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+
+ BKE_paint_reset_overlay_invalid(PAINT_INVALID_OVERLAY_CURVE);
return 1;
}
+
+
static int project_brush_radius(ViewContext *vc,
float radius,
const float location[3])
@@ -397,36 +529,25 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc,
/* Draw an overlay that shows what effect the brush's texture will
* 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, PaintMode mode)
+static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
+ ViewContext *vc, int x, int y, float zoom, bool col, bool primary)
{
rctf quad;
- bool col;
/* check for overlay mode */
- if (!((brush->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL && brush->mtex.tex) ||
- ((brush->overlay_flags & BRUSH_OVERLAY_PRIMARY) &&
- ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED))))
+ MTex *mtex = (primary) ? &brush->mtex : &brush->mask_mtex;
+ bool valid = (primary) ? (brush->overlay_flags & BRUSH_OVERLAY_PRIMARY) != 0 :
+ (brush->overlay_flags & BRUSH_OVERLAY_SECONDARY) != 0;
+ int overlay_alpha = (primary) ? brush->texture_overlay_alpha : brush->mask_overlay_alpha;
+
+ if (!((mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL && mtex->tex) ||
+ (valid &&
+ ELEM(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 |
- GL_CURRENT_BIT |
- GL_DEPTH_BUFFER_BIT |
- GL_ENABLE_BIT |
- GL_LINE_BIT |
- GL_POLYGON_BIT |
- GL_STENCIL_BUFFER_BIT |
- GL_TRANSFORM_BIT |
- GL_VIEWPORT_BIT |
- GL_TEXTURE_BIT);
-
- if (load_tex(brush, vc, zoom, col)) {
+ if (load_tex(brush, vc, zoom, col, primary)) {
glEnable(GL_BLEND);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -437,7 +558,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glPushMatrix();
glLoadIdentity();
- if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* brush rotation */
glTranslatef(0.5, 0.5, 0);
glRotatef((double)RAD2DEGF(ups->brush_rotation),
@@ -445,7 +566,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glTranslatef(-0.5f, -0.5f, 0);
/* scale based on tablet pressure */
- if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
+ if (primary && ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
glTranslatef(0.5f, 0.5f, 0);
glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1);
glTranslatef(-0.5f, -0.5f, 0);
@@ -466,7 +587,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
quad.ymax = y + radius;
}
}
- else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) {
+ else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
quad.xmin = 0;
quad.ymin = 0;
quad.xmax = BLI_rcti_size_x(&vc->ar->winrct);
@@ -482,7 +603,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0);
- glRotatef(RAD2DEGF(brush->mtex.rot), 0, 0, 1);
+ glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1);
glMatrixMode(GL_TEXTURE);
}
@@ -491,12 +612,12 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glColor4f(1.0,
1.0,
1.0,
- brush->texture_overlay_alpha / 100.0f);
+ 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);
+ overlay_alpha / 100.0f);
/* draw textured quad */
glBegin(GL_QUADS);
@@ -512,11 +633,103 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glPopMatrix();
- if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL) {
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
}
+}
+
+/* Draw an overlay that shows what effect the brush's texture will
+ * have on brush strength */
+static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
+ ViewContext *vc, int x, int y, float zoom)
+{
+ rctf quad;
+ /* check for overlay mode */
+
+ if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR))
+ {
+ return;
+ }
+
+ if (load_tex_cursor(brush, vc, zoom)) {
+ glEnable(GL_BLEND);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ glDepthFunc(GL_ALWAYS);
+
+ /* scale based on tablet pressure */
+ if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
+ glTranslatef(0.5f, 0.5f, 0);
+ glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1);
+ glTranslatef(-0.5f, -0.5f, 0);
+ }
+
+ if (ups->draw_anchored) {
+ const float *aim = ups->anchored_initial_mouse;
+ quad.xmin = aim[0] - ups->anchored_size;
+ quad.ymin = aim[1] - ups->anchored_size;
+ quad.xmax = aim[0] + ups->anchored_size;
+ quad.ymax = aim[1] + ups->anchored_size;
+ }
+ else {
+ const int radius = BKE_brush_size_get(vc->scene, brush) * zoom;
+ quad.xmin = x - radius;
+ quad.ymin = y - radius;
+ quad.xmax = x + radius;
+ quad.ymax = y + radius;
+ }
+
+ glColor4f(U.sculpt_paint_overlay_col[0],
+ U.sculpt_paint_overlay_col[1],
+ U.sculpt_paint_overlay_col[2],
+ brush->cursor_overlay_alpha / 100.0f);
+
+ /* draw textured quad */
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0);
+ glVertex2f(quad.xmin, quad.ymin);
+ glTexCoord2f(1, 0);
+ glVertex2f(quad.xmax, quad.ymin);
+ glTexCoord2f(1, 1);
+ glVertex2f(quad.xmax, quad.ymax);
+ glTexCoord2f(0, 1);
+ glVertex2f(quad.xmin, quad.ymax);
+ glEnd();
+ }
+}
+
+static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
+ ViewContext *vc, int x, int y, float zoom, PaintMode mode)
+{
+ /* color means that primary brush texture is colured and secondary is used for alpha/mask control */
+ bool 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 |
+ GL_CURRENT_BIT |
+ GL_DEPTH_BUFFER_BIT |
+ GL_ENABLE_BIT |
+ GL_LINE_BIT |
+ GL_POLYGON_BIT |
+ GL_STENCIL_BUFFER_BIT |
+ GL_TRANSFORM_BIT |
+ GL_VIEWPORT_BIT |
+ GL_TEXTURE_BIT);
+
+
+ /* coloured overlay should be drawn separately */
+ if (col) {
+ paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true);
+ paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false);
+ paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
+ } else {
+ paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
+ paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
+ }
glPopAttrib();
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 14330229aba..de3c4db3b60 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -3796,6 +3796,7 @@ static void *do_projectpaint_thread(void *ph_v)
/* for smear only */
float pos_ofs[2] = {0};
float co[2];
+ float texmask = 1.0;
float mask = 1.0f; /* airbrush wont use mask */
unsigned short mask_short;
const float radius = (float)BKE_brush_size_get(ps->scene, brush);
@@ -3909,7 +3910,8 @@ static void *do_projectpaint_thread(void *ph_v)
}
if (ps->is_maskbrush) {
- alpha *= BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
+ texmask = BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
+ alpha *= texmask;
}
if (!ps->do_masking) {
@@ -3922,7 +3924,7 @@ static void *do_projectpaint_thread(void *ph_v)
falloff = 1.0f - falloff;
falloff = 1.0f - (falloff * falloff);
- mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, brush) * falloff));
+ mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, brush) * falloff)) * texmask;
if (mask_short > projPixel->mask_max) {
mask = ((float)mask_short) / 65535.0f;
projPixel->mask_max = mask_short;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index ef7fbec3742..4369c6dfabd 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -523,7 +523,7 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode");
RNA_def_property_enum_items(prop, prop_mask_paint_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
- RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
+ RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_update");
}
static void rna_def_sculpt_capabilities(BlenderRNA *brna)