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-03-31 04:38:50 +0400
committerAntony Riakiotakis <kalast@gmail.com>2013-03-31 04:38:50 +0400
commit1fea6220a2418b07bec8bbf49da00cc77094076f (patch)
treee674dbe323e533ec54c7d7f6937bcfdf09247a29
parent68ac08681a084ae719fdfb3c3063593970d2d7b3 (diff)
Woot woot commit.
Stencil style texture mapping. Ready for field testing and user feedback. This commit adds stencil like brushes, like those that existed on old ptex branch. (with the exception of clip colour) To control the position of the stencil, you use Q: translation Shift - Q: scaling Ctrl - Q: rotation There's extra work that has been done to make this work: * Support for coloured overlay in vertex/texture painting * Also made A button do stroke mode selection like in sculpt mode, when mask painting is inactive. There are some TODOs to work on during bcon3: * Support tiled and stencil mode in 2D painting. Support alpha textures also. * Tidy up overlay code. There's some confusion there due to the way we use the primary brush texture sometimes for alpha, other times for colour control. WIP design docs will be in http://wiki.blender.org/index.php/User:Psy-Fi/New_Brush_Tool_Design
-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}
};