Vertex Paint: Alpha Support
GSOC 2017 by Darshan Kadu, see: D2859. This is a partial merge of some of the features from the soc-2017-vertex_paint branch. - Alpha painting & drawing. - 10 new color blending modes. - Support for vertex select in vertex paint mode.
This commit is contained in:
@@ -55,7 +55,7 @@ class VIEW3D_HT_header(Header):
|
||||
|
||||
# Occlude geometry
|
||||
if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
|
||||
(mode == 'WEIGHT_PAINT')):
|
||||
(mode in {'WEIGHT_PAINT', 'VERTEX_PAINT'})):
|
||||
row.prop(view, "use_occlude_geometry", text="")
|
||||
|
||||
# Proportional editing
|
||||
@@ -170,7 +170,7 @@ class VIEW3D_MT_editor_menus(Menu):
|
||||
mesh = obj.data
|
||||
if mesh.use_paint_mask:
|
||||
layout.menu("VIEW3D_MT_select_paint_mask")
|
||||
elif mesh.use_paint_mask_vertex and mode_string == 'PAINT_WEIGHT':
|
||||
elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
|
||||
layout.menu("VIEW3D_MT_select_paint_mask_vertex")
|
||||
elif mode_string != 'SCULPT':
|
||||
layout.menu("VIEW3D_MT_select_%s" % mode_string.lower())
|
||||
@@ -1780,6 +1780,7 @@ class VIEW3D_MT_paint_vertex(Menu):
|
||||
layout.operator("paint.vertex_color_set")
|
||||
layout.operator("paint.vertex_color_smooth")
|
||||
layout.operator("paint.vertex_color_dirt")
|
||||
layout.operator("paint.vertex_color_from_weight")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
||||
@@ -1168,6 +1168,8 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
|
||||
# row.prop(brush, "use_pressure_jitter", toggle=True, text="")
|
||||
col.separator()
|
||||
col.prop(brush, "vertex_tool", text="Blend")
|
||||
col.prop(brush, "use_accumulate")
|
||||
col.prop(brush, "use_alpha")
|
||||
|
||||
col.separator()
|
||||
col.template_ID(settings, "palette", new="palette.new")
|
||||
|
||||
@@ -220,6 +220,7 @@ typedef struct SculptSession {
|
||||
|
||||
/* For non-airbrush painting to re-apply from the original (MLoop aligned). */
|
||||
unsigned int *previous_color;
|
||||
unsigned int *previous_accum;
|
||||
} vpaint;
|
||||
|
||||
struct {
|
||||
|
||||
@@ -752,8 +752,18 @@ static void cdDM_drawMappedFaces(
|
||||
/* avoid buffer problems in following code */
|
||||
}
|
||||
else if (setDrawOptions == NULL) {
|
||||
const bool show_alpha = true;
|
||||
if (show_alpha) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
/* just draw the entire face array */
|
||||
GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, 0, tot_tri_elem);
|
||||
|
||||
if (show_alpha) {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
|
||||
@@ -1525,8 +1535,8 @@ static void cdDM_buffer_copy_mcol(
|
||||
|
||||
for (i = 0; i < totpoly; i++, mpoly++) {
|
||||
for (j = 0; j < mpoly->totloop; j++) {
|
||||
copy_v3_v3_uchar(&varray[start], &mloopcol[mpoly->loopstart + j].r);
|
||||
start += 3;
|
||||
copy_v4_v4_uchar(&varray[start], &mloopcol[mpoly->loopstart + j].r);
|
||||
start += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,7 +466,7 @@ bool BKE_paint_select_vert_test(Object *ob)
|
||||
(ob->type == OB_MESH) &&
|
||||
(ob->data != NULL) &&
|
||||
(((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_VERT_SEL) &&
|
||||
(ob->mode & OB_MODE_WEIGHT_PAINT)
|
||||
(ob->mode & OB_MODE_WEIGHT_PAINT || ob->mode & OB_MODE_VERTEX_PAINT)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -680,6 +680,7 @@ void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss)
|
||||
gmap = &ss->mode.vpaint.gmap;
|
||||
|
||||
MEM_SAFE_FREE(ss->mode.vpaint.previous_color);
|
||||
MEM_SAFE_FREE(ss->mode.vpaint.previous_accum);
|
||||
}
|
||||
else if (ss->mode_type == OB_MODE_WEIGHT_PAINT) {
|
||||
gmap = &ss->mode.wpaint.gmap;
|
||||
@@ -737,7 +738,10 @@ void BKE_sculptsession_bm_to_me_for_render(Object *object)
|
||||
*/
|
||||
BKE_object_free_derived_caches(object);
|
||||
|
||||
MEM_SAFE_FREE(object->sculpt->pbvh);
|
||||
if (object->sculpt->pbvh) {
|
||||
BKE_pbvh_free(object->sculpt->pbvh);
|
||||
object->sculpt->pbvh = NULL;
|
||||
}
|
||||
|
||||
sculptsession_bm_to_me_update_data_only(object, false);
|
||||
|
||||
|
||||
@@ -1653,6 +1653,23 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Brush *br;
|
||||
br = (Brush *)BKE_libblock_find_name_ex(main, ID_BR, "Average");
|
||||
if (!br) {
|
||||
br = BKE_brush_add(main, "Average", OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT);
|
||||
br->vertexpaint_tool = PAINT_BLEND_AVERAGE;
|
||||
br->ob_mode = OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT;
|
||||
}
|
||||
|
||||
br = (Brush *)BKE_libblock_find_name_ex(main, ID_BR, "Smear");
|
||||
if (!br) {
|
||||
br = BKE_brush_add(main, "Smear", OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT);
|
||||
br->vertexpaint_tool = PAINT_BLEND_SMEAR;
|
||||
br->ob_mode = OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT;
|
||||
}
|
||||
}
|
||||
|
||||
FOREACH_NODETREE(main, ntree, id) {
|
||||
if (ntree->type == NTREE_COMPOSIT) {
|
||||
do_versions_compositor_render_passes(ntree);
|
||||
|
||||
@@ -282,6 +282,7 @@ bool ED_mesh_uv_texture_remove_active(struct Mesh *me);
|
||||
bool ED_mesh_uv_texture_remove_named(struct Mesh *me, const char *name);
|
||||
void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me);
|
||||
void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum);
|
||||
bool ED_mesh_color_ensure(struct Mesh *me, const char *name);
|
||||
int ED_mesh_color_add(struct Mesh *me, const char *name, const bool active_set);
|
||||
bool ED_mesh_color_remove_index(struct Mesh *me, const int n);
|
||||
bool ED_mesh_color_remove_active(struct Mesh *me);
|
||||
|
||||
@@ -464,6 +464,20 @@ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set)
|
||||
return layernum;
|
||||
}
|
||||
|
||||
bool ED_mesh_color_ensure(struct Mesh *me, const char *name)
|
||||
{
|
||||
BLI_assert(me->edit_btmesh == NULL);
|
||||
|
||||
if (!me->mloopcol && me->totloop) {
|
||||
CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name);
|
||||
BKE_mesh_update_customdata_pointers(me, true);
|
||||
}
|
||||
|
||||
DAG_id_tag_update(&me->id, 0);
|
||||
|
||||
return (me->mloopcol != NULL);
|
||||
}
|
||||
|
||||
bool ED_mesh_color_remove_index(Mesh *me, const int n)
|
||||
{
|
||||
CustomData *ldata = GET_CD_DATA(me, ldata);
|
||||
|
||||
@@ -52,6 +52,7 @@ set(SRC
|
||||
paint_undo.c
|
||||
paint_utils.c
|
||||
paint_vertex.c
|
||||
paint_vertex_color_ops.c
|
||||
paint_vertex_proj.c
|
||||
sculpt.c
|
||||
sculpt_undo.c
|
||||
|
||||
@@ -123,6 +123,8 @@ void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
|
||||
|
||||
unsigned int vpaint_get_current_col(struct Scene *scene, struct VPaint *vp);
|
||||
|
||||
/* paint_vertex_color_ops.c */
|
||||
void PAINT_OT_vertex_color_from_weight(struct wmOperatorType *ot);
|
||||
|
||||
/* paint_vertex_proj.c */
|
||||
struct VertProjHandle;
|
||||
|
||||
@@ -1349,6 +1349,7 @@ void ED_operatortypes_paint(void)
|
||||
WM_operatortype_append(PAINT_OT_vertex_color_hsv);
|
||||
WM_operatortype_append(PAINT_OT_vertex_color_invert);
|
||||
WM_operatortype_append(PAINT_OT_vertex_color_levels);
|
||||
WM_operatortype_append(PAINT_OT_vertex_color_from_weight);
|
||||
|
||||
/* face-select */
|
||||
WM_operatortype_append(PAINT_OT_face_select_linked);
|
||||
|
||||
@@ -83,6 +83,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;
|
||||
@@ -256,29 +258,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);
|
||||
}
|
||||
|
||||
DAG_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)
|
||||
{
|
||||
@@ -342,12 +321,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++) {
|
||||
@@ -356,9 +336,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 */
|
||||
@@ -465,7 +452,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;
|
||||
}
|
||||
@@ -512,7 +499,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;
|
||||
}
|
||||
@@ -612,15 +599,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;
|
||||
}
|
||||
@@ -645,7 +634,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;
|
||||
}
|
||||
@@ -670,7 +660,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;
|
||||
}
|
||||
@@ -695,7 +686,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;
|
||||
}
|
||||
@@ -728,7 +719,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;
|
||||
}
|
||||
@@ -761,24 +752,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;
|
||||
@@ -787,27 +1127,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];
|
||||
@@ -820,7 +1160,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1738,12 +2087,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 {
|
||||
@@ -1780,6 +2132,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) {
|
||||
@@ -3104,6 +3466,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) {
|
||||
@@ -3118,9 +3483,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
|
||||
else {
|
||||
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);
|
||||
@@ -3229,8 +3592,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;
|
||||
|
||||
@@ -3295,8 +3657,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;
|
||||
@@ -3315,7 +3676,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++) {
|
||||
@@ -3367,12 +3728,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)
|
||||
{
|
||||
@@ -3386,7 +3748,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;
|
||||
@@ -3416,9 +3778,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,
|
||||
@@ -3447,6 +3816,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;
|
||||
@@ -3459,7 +3829,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];
|
||||
@@ -3469,7 +3839,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;
|
||||
@@ -3547,6 +3917,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);
|
||||
@@ -3562,15 +3933,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);
|
||||
|
||||
111
source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
Normal file
111
source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/sculpt_paint/paint_vertex_color_ops.c
|
||||
* \ingroup edsculpt
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_deform.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_mesh.h"
|
||||
|
||||
#include "paint_intern.h" /* own include */
|
||||
|
||||
|
||||
static int vertex_weight_paint_mode_poll(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
Mesh *me = BKE_mesh_from_object(ob);
|
||||
return (ob && (ob->mode == OB_MODE_VERTEX_PAINT || ob->mode == OB_MODE_WEIGHT_PAINT)) &&
|
||||
(me && me->totpoly && me->dvert);
|
||||
}
|
||||
|
||||
static bool vertex_paint_from_weight(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
Mesh *me;
|
||||
const MPoly *mp;
|
||||
int vgroup_active;
|
||||
|
||||
if (((me = BKE_mesh_from_object(ob)) == NULL ||
|
||||
(ED_mesh_color_ensure(me, NULL)) == false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* TODO: respect selection. */
|
||||
mp = me->mpoly;
|
||||
vgroup_active = ob->actdef - 1;
|
||||
for (int i = 0; i < me->totpoly; i++, mp++) {
|
||||
MLoopCol *lcol = &me->mloopcol[mp->loopstart];
|
||||
uint j = 0;
|
||||
do{
|
||||
uint vidx = me->mloop[mp->loopstart + j].v;
|
||||
const float weight = defvert_find_weight(&me->dvert[vidx], vgroup_active);
|
||||
const uchar grayscale = weight * 255;
|
||||
lcol->r = grayscale;
|
||||
lcol->b = grayscale;
|
||||
lcol->g = grayscale;
|
||||
lcol++;
|
||||
j++;
|
||||
} while (j < mp->totloop);
|
||||
}
|
||||
|
||||
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int vertex_paint_from_weight_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
if (vertex_paint_from_weight(C)) {
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Vertex Color from Weight";
|
||||
ot->idname = "PAINT_OT_vertex_color_from_weight";
|
||||
ot->description = "Converts active weight into greyscale vertex colors";
|
||||
|
||||
/* api callback */
|
||||
ot->exec = vertex_paint_from_weight_exec;
|
||||
ot->poll = vertex_weight_paint_mode_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* TODO: invert, alpha */
|
||||
}
|
||||
@@ -192,14 +192,14 @@ typedef struct {
|
||||
bool original;
|
||||
} SculptSearchSphereData;
|
||||
|
||||
void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test);
|
||||
void sculpt_brush_test_init(struct SculptSession *ss, SculptBrushTest *test);
|
||||
bool sculpt_brush_test(SculptBrushTest *test, const float co[3]);
|
||||
bool sculpt_brush_test_sq(SculptBrushTest *test, const float co[3]);
|
||||
bool sculpt_brush_test_fast(const SculptBrushTest *test, const float co[3]);
|
||||
bool sculpt_brush_test_cube(SculptBrushTest *test, const float co[3], float local[4][4]);
|
||||
bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v);
|
||||
float tex_strength(
|
||||
SculptSession *ss, struct Brush *br,
|
||||
struct SculptSession *ss, struct Brush *br,
|
||||
const float point[3],
|
||||
const float len,
|
||||
const short vno[3],
|
||||
|
||||
@@ -8457,8 +8457,8 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
|
||||
else {
|
||||
Mesh *me = ob->data;
|
||||
if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) &&
|
||||
/* currently vertex select only supports weight paint */
|
||||
(ob->mode & OB_MODE_WEIGHT_PAINT))
|
||||
/* currently vertex select supports weight paint and vertex paint*/
|
||||
((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT)))
|
||||
{
|
||||
bbs_mesh_solid_verts(scene, ob);
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
|
||||
PointerRNA meshptr;
|
||||
|
||||
RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr);
|
||||
if (ob->mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT)) {
|
||||
if (ob->mode & (OB_MODE_TEXTURE_PAINT)) {
|
||||
uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -82,7 +82,7 @@ static const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
|
||||
/* normal */
|
||||
{GL_ARRAY_BUFFER, 4}, /* we copy 3 shorts per normal but we add a fourth for alignment */
|
||||
/* mcol */
|
||||
{GL_ARRAY_BUFFER, 3},
|
||||
{GL_ARRAY_BUFFER, 4},
|
||||
/* uv */
|
||||
{GL_ARRAY_BUFFER, 2},
|
||||
/* uv for texpaint */
|
||||
@@ -690,7 +690,7 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
|
||||
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->colors->id);
|
||||
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
|
||||
|
||||
GLStates |= GPU_BUFFER_COLOR_STATE;
|
||||
}
|
||||
|
||||
@@ -318,6 +318,18 @@ enum {
|
||||
PAINT_BLEND_DARKEN = 6,
|
||||
PAINT_BLEND_AVERAGE = 7,
|
||||
PAINT_BLEND_SMEAR = 8,
|
||||
PAINT_BLEND_COLORDODGE = 9,
|
||||
PAINT_BLEND_DIFFERENCE = 10,
|
||||
PAINT_BLEND_SCREEN = 11,
|
||||
PAINT_BLEND_HARDLIGHT = 12,
|
||||
PAINT_BLEND_OVERLAY = 13,
|
||||
PAINT_BLEND_SOFTLIGHT = 14,
|
||||
PAINT_BLEND_EXCLUSION = 15,
|
||||
PAINT_BLEND_LUMINOCITY = 16,
|
||||
PAINT_BLEND_SATURATION = 17,
|
||||
PAINT_BLEND_HUE = 18,
|
||||
PAINT_BLEND_ALPHA_SUB = 19,
|
||||
PAINT_BLEND_ALPHA_ADD = 20,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -94,8 +94,21 @@ EnumPropertyItem rna_enum_brush_vertex_tool_items[] = {
|
||||
{PAINT_BLEND_BLUR, "BLUR", ICON_BRUSH_BLUR, "Blur", "Blur the color with surrounding values"},
|
||||
{PAINT_BLEND_LIGHTEN, "LIGHTEN", ICON_BRUSH_LIGHTEN, "Lighten", "Use lighten blending mode while painting"},
|
||||
{PAINT_BLEND_DARKEN, "DARKEN", ICON_BRUSH_DARKEN, "Darken", "Use darken blending mode while painting"},
|
||||
{PAINT_BLEND_AVERAGE, "AVERAGE", ICON_BRUSH_BLUR, "Average", "Use average blending mode while painting" },
|
||||
{PAINT_BLEND_SMEAR, "SMEAR", ICON_BRUSH_BLUR, "Smear", "Use smear blending mode while painting" },
|
||||
{PAINT_BLEND_AVERAGE, "AVERAGE", ICON_BRUSH_BLUR, "Average", "Use average blending mode while painting"},
|
||||
{PAINT_BLEND_SMEAR, "SMEAR", ICON_BRUSH_BLUR, "Smear", "Use smear blending mode while painting"},
|
||||
{PAINT_BLEND_COLORDODGE, "COLORDODGE", ICON_BRUSH_BLUR, "Color Dodge", "Use color dodge blending mode while painting" },
|
||||
{PAINT_BLEND_DIFFERENCE, "DIFFERENCE", ICON_BRUSH_BLUR, "Difference", "Use difference blending mode while painting"},
|
||||
{PAINT_BLEND_SCREEN, "SCREEN", ICON_BRUSH_BLUR, "Screen", "Use screen blending mode while painting"},
|
||||
{PAINT_BLEND_HARDLIGHT, "HARDLIGHT", ICON_BRUSH_BLUR, "Hardlight", "Use hardlight blending mode while painting"},
|
||||
{PAINT_BLEND_OVERLAY, "OVERLAY", ICON_BRUSH_BLUR, "Overlay", "Use overlay blending mode while painting"},
|
||||
{PAINT_BLEND_SOFTLIGHT, "SOFTLIGHT", ICON_BRUSH_BLUR, "Softlight", "Use softlight blending mode while painting"},
|
||||
{PAINT_BLEND_EXCLUSION, "EXCLUSION", ICON_BRUSH_BLUR, "Exclusion", "Use exclusion blending mode while painting"},
|
||||
{PAINT_BLEND_LUMINOCITY, "LUMINOCITY", ICON_BRUSH_BLUR, "Luminocity", "Use luminocity blending mode while painting"},
|
||||
{PAINT_BLEND_SATURATION, "SATURATION", ICON_BRUSH_BLUR, "Saturation", "Use saturation blending mode while painting"},
|
||||
{PAINT_BLEND_HUE, "HUE", ICON_BRUSH_BLUR, "Hue", "Use hue blending mode while painting"},
|
||||
{PAINT_BLEND_ALPHA_SUB, "ERASE_ALPHA", 0, "Erase Alpha", "Erase alpha while painting"},
|
||||
{PAINT_BLEND_ALPHA_ADD, "ADD_ALPHA", 0, "Add Alpha", "Add alpha while painting"},
|
||||
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -1250,7 +1263,7 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
/* only for projection paint, TODO, other paint modes */
|
||||
/* only for projection paint & vertex paint, TODO, other paint modes */
|
||||
prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_LOCK_ALPHA);
|
||||
RNA_def_property_ui_text(prop, "Alpha", "When this is disabled, lock alpha while painting");
|
||||
|
||||
Reference in New Issue
Block a user