diff options
19 files changed, 650 insertions, 89 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 2a96905a359..1086f22b8da 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -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() diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 8562cb419b4..6a319b45b06 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -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") diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 88693600653..015fd7c8a14 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -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 { diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index e97de07752e..2ed5cc450a4 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -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; } } } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 25ea6ad079f..05d53ae4771 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -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); diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 40fed37b1b0..8459e080f99 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -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); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index de798b1fce2..c867df2d01a 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -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); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 3294490d5b1..737c8ac665d 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -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); diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 46753df4e13..fa669d236b9 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -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 diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 0ec7d97a04d..16570b0fdde 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -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; diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 4ebf14ed0b9..23231b7ccc7 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -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); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index a88b834d601..18b71dedc07 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -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); diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c new file mode 100644 index 00000000000..5325d660f91 --- /dev/null +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c @@ -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 */ +} diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 850d4631311..3d1c7e94d17 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -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], diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 73fd77db477..5f01092f5b0 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -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); } diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index bf1bdf68619..70caee66b29 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -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 { diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 73c4d8a6804..e288c74fee6 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -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; } diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index eecfd88606f..67a35d4e207 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -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 { diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 7b3636f1615..fe8e1bb7e6e 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -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"); |