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:
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_vertex.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c517
1 files changed, 444 insertions, 73 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 9046a768eaf..c3fb67816da 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -84,6 +84,8 @@
#include "sculpt_intern.h"
#include "paint_intern.h" /* own include */
+#define EPS_SATURATION 0.0005f
+
/* Use for 'blur' brush, align with PBVH nodes, created and freed on each update. */
struct VPaintAverageAccum {
uint len;
@@ -257,29 +259,6 @@ static void do_shared_vertexcol(Mesh *me, bool *mlooptag)
MEM_freeN(scol);
}
-static bool make_vertexcol(Object *ob) /* single ob */
-{
- Mesh *me;
-
- if (ID_IS_LINKED_DATABLOCK(ob) ||
- ((me = BKE_mesh_from_object(ob)) == NULL) ||
- (me->totpoly == 0) ||
- (me->edit_btmesh))
- {
- return false;
- }
-
- /* copies from shadedisplist to mcol */
- if (!me->mloopcol && me->totloop) {
- CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
- BKE_mesh_update_customdata_pointers(me, true);
- }
-
- DEG_id_tag_update(&me->id, 0);
-
- return (me->mloopcol != NULL);
-}
-
/* mirror_vgroup is set to -1 when invalid */
static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
{
@@ -343,12 +322,13 @@ bool ED_vpaint_fill(Object *ob, uint paintcol)
int i, j;
if (((me = BKE_mesh_from_object(ob)) == NULL) ||
- (me->mloopcol == NULL && (make_vertexcol(ob) == false)))
+ (ED_mesh_color_ensure(me, NULL) == false))
{
return false;
}
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
mp = me->mpoly;
for (i = 0; i < me->totpoly; i++, mp++) {
@@ -357,9 +337,16 @@ bool ED_vpaint_fill(Object *ob, uint paintcol)
if (use_face_sel && !(mp->flag & ME_FACE_SEL))
continue;
- for (j = 0; j < mp->totloop; j++, lcol++) {
- *(int *)lcol = paintcol;
- }
+ j = 0;
+ do {
+ uint vidx = me->mloop[mp->loopstart + j].v;
+ if (!(use_vert_sel && !(me->mvert[vidx].flag & SELECT))) {
+ *(int *)lcol = paintcol;
+ }
+ lcol++;
+ j++;
+ } while (j < mp->totloop);
+
}
/* remove stale me->mcol, will be added later */
@@ -466,7 +453,7 @@ bool ED_vpaint_smooth(Object *ob)
bool *mlooptag;
if (((me = BKE_mesh_from_object(ob)) == NULL) ||
- (me->mloopcol == NULL && (make_vertexcol(ob) == false)))
+ (ED_mesh_color_ensure(me, NULL) == false))
{
return false;
}
@@ -513,7 +500,7 @@ bool ED_vpaint_color_transform(
const MPoly *mp;
if (((me = BKE_mesh_from_object(ob)) == NULL) ||
- (me->mloopcol == NULL && (make_vertexcol(ob) == false)))
+ (ED_mesh_color_ensure(me, NULL) == false))
{
return false;
}
@@ -613,15 +600,17 @@ BLI_INLINE uint mcol_blend(uint col1, uint col2, int fac)
int r1 = cp1[0] * cp1[0];
int g1 = cp1[1] * cp1[1];
int b1 = cp1[2] * cp1[2];
+ int a1 = cp1[3] * cp1[3];
int r2 = cp2[0] * cp2[0];
int g2 = cp2[1] * cp2[1];
int b2 = cp2[2] * cp2[2];
+ int a2 = cp2[3] * cp2[3];
cp[0] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * r1 + fac * r2), 255)));
cp[1] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * g1 + fac * g2), 255)));
cp[2] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * b1 + fac * b2), 255)));
- cp[3] = 255;
+ cp[3] = round_fl_to_uchar(sqrtf(divide_round_i((mfac * a1 + fac * a2), 255)));
return col;
}
@@ -646,7 +635,8 @@ BLI_INLINE uint mcol_add(uint col1, uint col2, int fac)
cp[1] = (temp > 254) ? 255 : temp;
temp = cp1[2] + divide_round_i((fac * cp2[2]), 255);
cp[2] = (temp > 254) ? 255 : temp;
- cp[3] = 255;
+ temp = cp1[3] + divide_round_i((fac * cp2[3]), 255);
+ cp[3] = (temp > 254) ? 255 : temp;
return col;
}
@@ -671,7 +661,8 @@ BLI_INLINE uint mcol_sub(uint col1, uint col2, int fac)
cp[1] = (temp < 0) ? 0 : temp;
temp = cp1[2] - divide_round_i((fac * cp2[2]), 255);
cp[2] = (temp < 0) ? 0 : temp;
- cp[3] = 255;
+ temp = cp1[3] - divide_round_i((fac * cp2[3]), 255);
+ cp[3] = (temp < 0) ? 0 : temp;
return col;
}
@@ -696,7 +687,7 @@ BLI_INLINE uint mcol_mul(uint col1, uint col2, int fac)
cp[0] = divide_round_i(mfac * cp1[0] * 255 + fac * cp2[0] * cp1[0], 255 * 255);
cp[1] = divide_round_i(mfac * cp1[1] * 255 + fac * cp2[1] * cp1[1], 255 * 255);
cp[2] = divide_round_i(mfac * cp1[2] * 255 + fac * cp2[2] * cp1[2], 255 * 255);
- cp[3] = 255;
+ cp[3] = divide_round_i(mfac * cp1[3] * 255 + fac * cp2[3] * cp1[3], 255 * 255);
return col;
}
@@ -729,7 +720,7 @@ BLI_INLINE uint mcol_lighten(uint col1, uint col2, int fac)
cp[0] = divide_round_i(mfac * cp1[0] + fac * cp2[0], 255);
cp[1] = divide_round_i(mfac * cp1[1] + fac * cp2[1], 255);
cp[2] = divide_round_i(mfac * cp1[2] + fac * cp2[2], 255);
- cp[3] = 255;
+ cp[3] = divide_round_i(mfac * cp1[3] + fac * cp2[3], 255);
return col;
}
@@ -762,24 +753,373 @@ BLI_INLINE uint mcol_darken(uint col1, uint col2, int fac)
cp[0] = divide_round_i((mfac * cp1[0] + fac * cp2[0]), 255);
cp[1] = divide_round_i((mfac * cp1[1] + fac * cp2[1]), 255);
cp[2] = divide_round_i((mfac * cp1[2] + fac * cp2[2]), 255);
- cp[3] = 255;
+ cp[3] = divide_round_i((mfac * cp1[3] + fac * cp2[3]), 255);
+ return col;
+}
+
+BLI_INLINE uint mcol_colordodge(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac,temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ temp = (cp2[0] == 255) ? 255 : min_ii((cp1[0] * 225) / (255 - cp2[0]), 255);
+ cp[0] = (mfac * cp1[0] + temp * fac) / 255;
+ temp = (cp2[1] == 255) ? 255 : min_ii((cp1[1] * 225) / (255 - cp2[1]), 255);
+ cp[1] = (mfac * cp1[1] + temp * fac) / 255;
+ temp = (cp2[2] == 255) ? 255 : min_ii((cp1[2] * 225 )/ (255 - cp2[2]), 255);
+ cp[2] = (mfac * cp1[2] + temp * fac) / 255;
+ temp = (cp2[3] == 255) ? 255 : min_ii((cp1[3] * 225) / (255 - cp2[3]), 255);
+ cp[3] = (mfac * cp1[3] + temp * fac) / 255;
+ return col;
+}
+
+BLI_INLINE uint mcol_difference(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac, temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ temp = abs(cp1[0] - cp2[0]);
+ cp[0] = (mfac * cp1[0] + temp * fac) / 255;
+ temp = abs(cp1[1] - cp2[1]);
+ cp[1] = (mfac * cp1[1] + temp * fac) / 255;
+ temp = abs(cp1[2] - cp2[2]);
+ cp[2] = (mfac * cp1[2] + temp * fac) / 255;
+ temp = abs(cp1[3] - cp2[3]);
+ cp[3] = (mfac * cp1[3] + temp * fac) / 255;
+ return col;
+}
+
+BLI_INLINE uint mcol_screen(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac, temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ temp = max_ii(255 - (((255 - cp1[0]) * (255 - cp2[0])) / 255), 0);
+ cp[0] = (mfac * cp1[0] + temp * fac) / 255;
+ temp = max_ii(255 - (((255 - cp1[1]) * (255 - cp2[1])) / 255), 0);
+ cp[1] = (mfac * cp1[1] + temp * fac) / 255;
+ temp = max_ii(255 - (((255 - cp1[2]) * (255 - cp2[2])) / 255), 0);
+ cp[2] = (mfac * cp1[2] + temp * fac) / 255;
+ temp = max_ii(255 - (((255 - cp1[3]) * (255 - cp2[3])) / 255), 0);
+ cp[3] = (mfac * cp1[3] + temp * fac) / 255;
+ return col;
+}
+
+BLI_INLINE uint mcol_hardlight(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac, temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ int i = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (cp2[i] > 127) {
+ temp = 255 - ((255 - 2 * (cp2[i] - 127)) * (255 - cp1[i]) / 255);
+ }
+ else {
+ temp = (2 * cp2[i] * cp1[i]) >> 8;
+ }
+ cp[i] = min_ii((mfac * cp1[i] + temp * fac) / 255, 255);
+ }
+ return col;
+}
+
+BLI_INLINE uint mcol_overlay(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac, temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ int i = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (cp1[i] > 127) {
+ temp = 255 - ((255 - 2 * (cp1[i] - 127)) * (255 - cp2[i]) / 255);
+ }
+ else {
+ temp = (2 * cp2[i] * cp1[i]) >> 8;
+ }
+ cp[i] = min_ii((mfac * cp1[i] + temp * fac) / 255, 255);
+ }
+ return col;
+}
+
+BLI_INLINE uint mcol_softlight(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac, temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ int i = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (cp1[i] < 127) {
+ temp = ((2 * ((cp2[i] / 2) + 64)) * cp1[i]) / 255;
+ }
+ else {
+ temp = 255 - (2 * (255 - ((cp2[i] / 2) + 64)) * (255 - cp1[i]) / 255);
+ }
+ cp[i] = (temp * fac + cp1[i] * mfac) / 255;
+ }
+ return col;
+}
+
+BLI_INLINE uint mcol_exclusion(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac, temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ int i = 0;
+
+ for (i = 0; i < 4; i++) {
+ temp = 127 - ((2 * (cp1[i] - 127) * (cp2[i] - 127)) / 255);
+ cp[i] = (temp * fac + cp1[i] * mfac) / 255;
+ }
+ return col;
+}
+
+BLI_INLINE uint mcol_luminosity(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(cp1[0] / 255.0f, cp1[1] / 255.0f, cp1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(cp2[0] / 255.0f, cp2[1] / 255.0f, cp2[2] / 255.0f, &h2, &s2, &v2);
+
+ v1 = v2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ cp[0] = ((int)(r * 255.0f) * fac + mfac * cp1[0]) / 255;
+ cp[1] = ((int)(g * 255.0f) * fac + mfac * cp1[1]) / 255;
+ cp[2] = ((int)(b * 255.0f) * fac + mfac * cp1[2]) / 255;
+ cp[3] = ((int)(cp2[3]) * fac + mfac * cp1[3]) / 255;
+ return col;
+}
+
+BLI_INLINE uint mcol_saturation(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(cp1[0] / 255.0f, cp1[1] / 255.0f, cp1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(cp2[0] / 255.0f, cp2[1] / 255.0f, cp2[2] / 255.0f, &h2, &s2, &v2);
+
+ if (s1 > EPS_SATURATION) {
+ s1 = s2;
+ }
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ cp[0] = ((int)(r * 255.0f) * fac + mfac * cp1[0]) / 255;
+ cp[1] = ((int)(g * 255.0f) * fac + mfac * cp1[1]) / 255;
+ cp[2] = ((int)(b * 255.0f) * fac + mfac * cp1[2]) / 255;
+ return col;
+}
+
+BLI_INLINE uint mcol_hue(uint col1, uint col2, int fac)
+{
+ uchar *cp1, *cp2, *cp;
+ int mfac;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ mfac = 255 - fac;
+
+ cp1 = (uchar *)&col1;
+ cp2 = (uchar *)&col2;
+ cp = (uchar *)&col;
+
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(cp1[0] / 255.0f, cp1[1] / 255.0f, cp1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(cp2[0] / 255.0f, cp2[1] / 255.0f, cp2[2] / 255.0f, &h2, &s2, &v2);
+
+ h1 = h2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ cp[0] = ((int)(r * 255.0f) * fac + mfac * cp1[0]) / 255;
+ cp[1] = ((int)(g * 255.0f) * fac + mfac * cp1[1]) / 255;
+ cp[2] = ((int)(b * 255.0f) * fac + mfac * cp1[2]) / 255;
+ cp[3] = ((int)(cp2[3]) * fac + mfac * cp1[3]) / 255;
+ return col;
+}
+
+BLI_INLINE uint mcol_alpha_add(uint col1, int fac)
+{
+ uchar *cp1, *cp;
+ int temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ cp1 = (uchar *)&col1;
+ cp = (uchar *)&col;
+
+ temp = cp1[3] + fac;
+ cp[3] = (temp > 254) ? 255 : temp;
+
return col;
}
+BLI_INLINE uint mcol_alpha_sub(uint col1, int fac)
+{
+ uchar *cp1, *cp;
+ int temp;
+ uint col = 0;
+
+ if (fac == 0) {
+ return col1;
+ }
+
+ cp1 = (uchar *)&col1;
+ cp = (uchar *)&col;
+
+ temp = cp1[3] - fac;
+ cp[3] = temp < 0 ? 0 : temp;
+
+ return col;
+}
+
+
/* wpaint has 'wpaint_blend_tool' */
-static uint vpaint_blend_tool(const int tool, const uint col,
- const uint paintcol, const int alpha_i)
+static uint vpaint_blend_tool(
+ const int tool, const uint col,
+ const uint paintcol, const int alpha_i)
{
switch (tool) {
case PAINT_BLEND_MIX:
- case PAINT_BLEND_BLUR: return mcol_blend(col, paintcol, alpha_i);
- case PAINT_BLEND_AVERAGE: return mcol_blend(col, paintcol, alpha_i);
- case PAINT_BLEND_SMEAR: return mcol_blend(col, paintcol, alpha_i);
- case PAINT_BLEND_ADD: return mcol_add(col, paintcol, alpha_i);
- case PAINT_BLEND_SUB: return mcol_sub(col, paintcol, alpha_i);
- case PAINT_BLEND_MUL: return mcol_mul(col, paintcol, alpha_i);
- case PAINT_BLEND_LIGHTEN: return mcol_lighten(col, paintcol, alpha_i);
- case PAINT_BLEND_DARKEN: return mcol_darken(col, paintcol, alpha_i);
+ case PAINT_BLEND_BLUR: return mcol_blend(col, paintcol, alpha_i);
+ case PAINT_BLEND_AVERAGE: return mcol_blend(col, paintcol, alpha_i);
+ case PAINT_BLEND_SMEAR: return mcol_blend(col, paintcol, alpha_i);
+ case PAINT_BLEND_ADD: return mcol_add(col, paintcol, alpha_i);
+ case PAINT_BLEND_SUB: return mcol_sub(col, paintcol, alpha_i);
+ case PAINT_BLEND_MUL: return mcol_mul(col, paintcol, alpha_i);
+ case PAINT_BLEND_LIGHTEN: return mcol_lighten(col, paintcol, alpha_i);
+ case PAINT_BLEND_DARKEN: return mcol_darken(col, paintcol, alpha_i);
+ case PAINT_BLEND_COLORDODGE: return mcol_colordodge(col, paintcol, alpha_i);
+ case PAINT_BLEND_DIFFERENCE: return mcol_difference(col, paintcol, alpha_i);
+ case PAINT_BLEND_SCREEN: return mcol_screen(col, paintcol, alpha_i);
+ case PAINT_BLEND_HARDLIGHT: return mcol_hardlight(col, paintcol, alpha_i);
+ case PAINT_BLEND_OVERLAY: return mcol_overlay(col, paintcol, alpha_i);
+ case PAINT_BLEND_SOFTLIGHT: return mcol_softlight(col, paintcol, alpha_i);
+ case PAINT_BLEND_EXCLUSION: return mcol_exclusion(col, paintcol, alpha_i);
+ case PAINT_BLEND_LUMINOCITY: return mcol_luminosity(col, paintcol, alpha_i);
+ case PAINT_BLEND_SATURATION: return mcol_saturation(col, paintcol, alpha_i);
+ case PAINT_BLEND_HUE: return mcol_hue(col, paintcol, alpha_i);
+ /* non-color */
+ case PAINT_BLEND_ALPHA_SUB: return mcol_alpha_sub(col, alpha_i);
+ case PAINT_BLEND_ALPHA_ADD: return mcol_alpha_add(col, alpha_i);
default:
BLI_assert(0);
return 0;
@@ -788,27 +1128,27 @@ static uint vpaint_blend_tool(const int tool, const uint col,
/* wpaint has 'wpaint_blend' */
static uint vpaint_blend(
- VPaint *vp, uint col, uint colorig,
- const uint paintcol, const int alpha_i,
+ VPaint *vp, uint color_curr, uint color_orig,
+ uint color_paint, const int alpha_i,
/* pre scaled from [0-1] --> [0-255] */
const int brush_alpha_value_i)
{
Brush *brush = BKE_paint_brush(&vp->paint);
const int tool = brush->vertexpaint_tool;
- col = vpaint_blend_tool(tool, col, paintcol, alpha_i);
+ uint color_blend = vpaint_blend_tool(tool, color_curr, color_paint, alpha_i);
/* if no spray, clip color adding with colorig & orig alpha */
if ((vp->flag & VP_SPRAY) == 0) {
- uint testcol, a;
+ uint color_test, a;
char *cp, *ct, *co;
-
- testcol = vpaint_blend_tool(tool, colorig, paintcol, brush_alpha_value_i);
-
- cp = (char *)&col;
- ct = (char *)&testcol;
- co = (char *)&colorig;
-
+
+ color_test = vpaint_blend_tool(tool, color_orig, color_paint, brush_alpha_value_i);
+
+ cp = (char *)&color_blend;
+ ct = (char *)&color_test;
+ co = (char *)&color_orig;
+
for (a = 0; a < 4; a++) {
if (ct[a] < co[a]) {
if (cp[a] < ct[a]) cp[a] = ct[a];
@@ -821,7 +1161,16 @@ static uint vpaint_blend(
}
}
- return col;
+ if ((brush->flag & BRUSH_LOCK_ALPHA) &&
+ !ELEM(tool, PAINT_BLEND_ALPHA_SUB, PAINT_BLEND_ALPHA_ADD))
+ {
+ char *cp, *cc;
+ cp = (char *)&color_blend;
+ cc = (char *)&color_curr;
+ cp[3] = cc[3];
+ }
+
+ return color_blend;
}
@@ -1739,12 +2088,15 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
{
/* Create maps */
struct SculptVertexPaintGeomMap *gmap = NULL;
+ const Brush *brush = NULL;
if (ob->mode == OB_MODE_VERTEX_PAINT) {
gmap = &ob->sculpt->mode.vpaint.gmap;
+ brush = BKE_paint_brush(&ts->vpaint->paint);
ob->sculpt->mode_type = OB_MODE_VERTEX_PAINT;
}
else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
gmap = &ob->sculpt->mode.wpaint.gmap;
+ brush = BKE_paint_brush(&ts->wpaint->paint);
ob->sculpt->mode_type = OB_MODE_WEIGHT_PAINT;
}
else {
@@ -1781,6 +2133,16 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
else {
MEM_SAFE_FREE(ob->sculpt->mode.vpaint.previous_color);
}
+
+ if (brush && brush->flag & BRUSH_ACCUMULATE) {
+ if (ob->sculpt->mode.vpaint.previous_accum == NULL) {
+ ob->sculpt->mode.vpaint.previous_accum =
+ MEM_callocN(me->totloop * sizeof(uint), "previous_color");
+ }
+ }
+ else {
+ MEM_SAFE_FREE(ob->sculpt->mode.vpaint.previous_accum);
+ }
}
else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
if ((ts->wpaint->flag & VP_SPRAY) == 0) {
@@ -3116,6 +3478,9 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
BKE_mesh_flush_select_from_polys(me);
}
+ else if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
+ BKE_mesh_flush_select_from_verts(me);
+ }
/* If the cache is not released by a cancel or a done, free it now. */
if (ob->sculpt->cache) {
@@ -3134,9 +3499,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
ob->mode |= mode_flag;
- if (me->mloopcol == NULL) {
- make_vertexcol(ob);
- }
+ ED_mesh_color_ensure(me, NULL);
if (vp == NULL)
vp = scene->toolsettings->vpaint = new_vpaint(0);
@@ -3250,8 +3613,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
if (me == NULL || me->totpoly == 0)
return false;
- if (me->mloopcol == NULL)
- make_vertexcol(ob);
+ ED_mesh_color_ensure(me, NULL);
if (me->mloopcol == NULL)
return false;
@@ -3316,8 +3678,7 @@ static void do_vpaint_brush_calc_average_color_cb_ex(
StrokeCache *cache = ss->cache;
uint *lcol = data->lcol;
char *col;
-
- const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
struct VPaintAverageAccum *accum = (struct VPaintAverageAccum *)data->custom_data + n;
accum->len = 0;
@@ -3336,7 +3697,7 @@ static void do_vpaint_brush_calc_average_color_cb_ex(
if (BKE_brush_curve_strength(data->brush, test.dist, cache->radius) > 0.0) {
/* If the vertex is selected for painting. */
const MVert *mv = &data->me->mvert[v_index];
- if (!use_face_sel || mv->flag & SELECT) {
+ if (!use_vert_sel || mv->flag & SELECT) {
accum->len += gmap->vert_to_loop[v_index].count;
/* if a vertex is within the brush region, then add it's color to the blend. */
for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) {
@@ -3388,12 +3749,13 @@ static void do_vpaint_brush_draw_task_cb_ex(
Scene *scene = CTX_data_scene(data->C);
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
SculptBrushTest test;
sculpt_brush_test_init(ss, &test);
- /* For each vertex*/
+ /* For each vertex */
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
@@ -3407,7 +3769,7 @@ static void do_vpaint_brush_draw_task_cb_ex(
const MVert *mv = &data->me->mvert[v_index];
/* If the vertex is selected for painting. */
- if (!use_face_sel || mv->flag & SELECT) {
+ if (!use_vert_sel || mv->flag & SELECT) {
/* Calc the dot prod. between ray norm on surf and current vert
* (ie splash prevention factor), and only paint front facing verts. */
const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
@@ -3437,9 +3799,16 @@ static void do_vpaint_brush_draw_task_cb_ex(
}
color_orig = ss->mode.vpaint.previous_color[l_index];
}
- const float final_alpha =
+ float final_alpha =
255 * brush_fade * brush_strength * view_dot *
tex_alpha * brush_alpha_pressure * grid_alpha;
+
+ if (brush->flag & BRUSH_ACCUMULATE) {
+ float mask_accum = ss->mode.vpaint.previous_accum[l_index];
+ final_alpha = min_ff(final_alpha + mask_accum, 255.0f);
+ ss->mode.vpaint.previous_accum[l_index] = final_alpha;
+ }
+
/* Mix the new color with the original based on final_alpha. */
lcol[l_index] = vpaint_blend(
data->vp, lcol[l_index], color_orig, color_final,
@@ -3468,6 +3837,7 @@ static void do_vpaint_brush_blur_task_cb_ex(
uint *lcol = data->lcol;
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
+ const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
SculptBrushTest test;
@@ -3480,7 +3850,7 @@ static void do_vpaint_brush_blur_task_cb_ex(
/* Test to see if the vertex coordinates are within the spherical brush region. */
if (sculpt_brush_test(&test, vd.co)) {
/* For grid based pbvh, take the vert whose loop cooresponds to the current grid.
- Otherwise, take the current vert. */
+ * Otherwise, take the current vert. */
const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
const MVert *mv = &data->me->mvert[v_index];
@@ -3490,7 +3860,7 @@ static void do_vpaint_brush_blur_task_cb_ex(
const float brush_fade = BKE_brush_curve_strength(brush, test.dist, cache->radius);
/* If the vertex is selected for painting. */
- if (!use_face_sel || mv->flag & SELECT) {
+ if (!use_vert_sel || mv->flag & SELECT) {
/* Get the average poly color */
uint color_final = 0;
int total_hit_loops = 0;
@@ -3568,6 +3938,7 @@ static void do_vpaint_brush_smear_task_cb_ex(
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
float brush_dir[3];
+ const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
@@ -3583,15 +3954,15 @@ static void do_vpaint_brush_smear_task_cb_ex(
/* Test to see if the vertex coordinates are within the spherical brush region. */
if (sculpt_brush_test(&test, vd.co)) {
/* For grid based pbvh, take the vert whose loop cooresponds to the current grid.
- Otherwise, take the current vert. */
+ * Otherwise, take the current vert. */
const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
const MVert *mv_curr = &data->me->mvert[v_index];
/* if the vertex is selected for painting. */
- if (!use_face_sel || mv_curr->flag & SELECT) {
+ if (!use_vert_sel || mv_curr->flag & SELECT) {
/* Calc the dot prod. between ray norm on surf and current vert
- (ie splash prevention factor), and only paint front facing verts. */
+ * (ie splash prevention factor), and only paint front facing verts. */
const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
if (view_dot > 0.0f) {
const float brush_fade = BKE_brush_curve_strength(brush, test.dist, cache->radius);