diff options
author | Joseph Eagar <joeedh@gmail.com> | 2021-11-03 22:15:13 +0300 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2021-11-03 22:15:13 +0300 |
commit | 1dcc741f433367b32ca2b7557bc4160f05e985c6 (patch) | |
tree | b52297a1214bbb0fd65438f573e4c906e79f41b5 /source | |
parent | 6cf734a2e5d2496d1b2d33bc7613b56a9f9fc2ec (diff) |
temp-sculpt-colors: commit patch
Diffstat (limited to 'source')
41 files changed, 647 insertions, 190 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index d71cb559911..4a34a7ec2fc 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 22 +#define BLENDER_FILE_SUBVERSION 26 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h index a2544e43c3d..e1e8eb598f4 100644 --- a/source/blender/blenkernel/BKE_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -54,9 +54,11 @@ enum { DT_TYPE_UV = 1 << 24, DT_TYPE_SHARP_FACE = 1 << 25, DT_TYPE_FREESTYLE_FACE = 1 << 26, -#define DT_TYPE_MAX 27 + DT_TYPE_PROPCOL = 1 << 27, +#define DT_TYPE_MAX 28 - DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT, + DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT | + DT_TYPE_PROPCOL, DT_TYPE_EDGE_ALL = DT_TYPE_SHARP_EDGE | DT_TYPE_SEAM | DT_TYPE_CREASE | DT_TYPE_BWEIGHT_EDGE | DT_TYPE_FREESTYLE_EDGE, DT_TYPE_LOOP_ALL = DT_TYPE_VCOL | DT_TYPE_LNOR | DT_TYPE_UV, @@ -74,7 +76,12 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type); int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type); #define DT_DATATYPE_IS_VERT(_dt) \ - ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT) + ELEM(_dt, \ + DT_TYPE_MDEFORMVERT, \ + DT_TYPE_SHAPEKEY, \ + DT_TYPE_SKIN, \ + DT_TYPE_BWEIGHT_VERT, \ + DT_TYPE_PROPCOL) #define DT_DATATYPE_IS_EDGE(_dt) \ ELEM(_dt, \ DT_TYPE_CREASE, \ @@ -94,7 +101,8 @@ enum { DT_MULTILAYER_INDEX_SHAPEKEY = 1, DT_MULTILAYER_INDEX_VCOL = 2, DT_MULTILAYER_INDEX_UV = 3, - DT_MULTILAYER_INDEX_MAX = 4, + DT_MULTILAYER_INDEX_PROPCOL = 4, + DT_MULTILAYER_INDEX_MAX = 5, }; /* Below we keep positive values for real layers idx (generated dynamically). */ diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 73413b61456..2d2406fb17b 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -467,6 +467,12 @@ typedef struct SculptSession { struct KeyBlock *shapekey_active; struct MPropCol *vcol; + float (*f3col)[3]; + struct MLoopCol *mcol; + + int vcol_domain; + int vcol_type; + float *vmask; /* Mesh connectivity maps. */ diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 056a7e2d897..929a2d03b97 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -25,6 +25,7 @@ #include "BLI_ghash.h" /* For embedding CCGKey in iterator. */ +#include "BKE_attribute.h" #include "BKE_ccg.h" #ifdef __cplusplus @@ -358,7 +359,6 @@ typedef struct PBVHVertexIter { struct MVert *mverts; int totvert; const int *vert_indices; - struct MPropCol *vcol; float *vmask; /* bmesh */ @@ -375,7 +375,6 @@ typedef struct PBVHVertexIter { short *no; float *fno; float *mask; - float *col; bool visible; } PBVHVertexIter; @@ -431,9 +430,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m if (vi.vmask) { \ vi.mask = &vi.vmask[vi.index]; \ } \ - if (vi.vcol) { \ - vi.col = vi.vcol[vi.index].color; \ - } \ } \ else { \ if (!BLI_gsetIterator_done(&vi.bm_unique_verts)) { \ @@ -489,6 +485,9 @@ struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh); PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node); void BKE_pbvh_node_color_buffer_free(PBVH *pbvh); +bool BKE_pbvh_get_color_layer(const struct Mesh *me, + CustomDataLayer **cl_out, + AttributeDomain *attr_out); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index d70b941695e..69773b43173 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1843,6 +1843,8 @@ void BKE_brush_sculpt_reset(Brush *br) br->density = 1.0f; br->flag &= ~BRUSH_SPACE_ATTEN; zero_v3(br->rgb); + add_v3_fl(br->rgb, 1.0f); + zero_v3(br->secondary_rgb); break; case SCULPT_TOOL_SMEAR: br->alpha = 1.0f; diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index b83621e8b79..c4414f93a87 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -150,6 +150,7 @@ bool BKE_object_data_transfer_get_dttypes_capacity(const int dtdata_types, case DT_TYPE_UV: ret = true; break; + case DT_TYPE_PROPCOL: case DT_TYPE_VCOL: *r_advanced_mixing = true; *r_threshold = true; @@ -230,12 +231,12 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type) return CD_FAKE_SHARP; case DT_TYPE_FREESTYLE_FACE: return CD_FREESTYLE_FACE; - case DT_TYPE_VCOL: return CD_MLOOPCOL; case DT_TYPE_LNOR: return CD_FAKE_LNOR; - + case DT_TYPE_PROPCOL: + return CD_PROP_COLOR; default: BLI_assert(0); } @@ -253,6 +254,8 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type) return DT_MULTILAYER_INDEX_UV; case DT_TYPE_VCOL: return DT_MULTILAYER_INDEX_VCOL; + case DT_TYPE_PROPCOL: + return DT_MULTILAYER_INDEX_PROPCOL; default: return DT_MULTILAYER_INDEX_INVALID; } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index d6030941c6d..53f3692a7bd 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -45,6 +45,7 @@ #include "BLT_translation.h" +#include "BKE_attribute.h" #include "BKE_brush.h" #include "BKE_ccg.h" #include "BKE_colortools.h" @@ -1673,7 +1674,31 @@ static void sculpt_update_object(Depsgraph *depsgraph, ss->multires.modifier = NULL; ss->multires.level = 0; ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK); - ss->vcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); + + CustomDataLayer *cl; + AttributeDomain domain; + + ss->vcol = NULL; + ss->mcol = NULL; + ss->f3col = NULL; + + if (BKE_pbvh_get_color_layer(me, &cl, &domain)) { + if (cl->type == CD_PROP_COLOR) { + ss->vcol = cl->data; + } + else if (cl->type == CD_PROP_FLOAT3) { + ss->f3col = cl->data; + } + else { + ss->mcol = cl->data; + } + + ss->vcol_domain = domain; + ss->vcol_type = cl->type; + } + else { + ss->vcol_type = -1; + } } /* Sculpt Face Sets. */ @@ -1798,17 +1823,53 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval) void BKE_sculpt_color_layer_create_if_needed(struct Object *object) { Mesh *orig_me = BKE_object_get_original_mesh(object); - if (!U.experimental.use_sculpt_vertex_colors) { - return; + + int types[] = {CD_PROP_COLOR, CD_PROP_FLOAT3, CD_MLOOPCOL}; + bool has_color = false; + + for (int i = 0; i < 3; i++) { + bool ok = CustomData_has_layer(&orig_me->vdata, types[i]); + ok = ok || CustomData_has_layer(&orig_me->ldata, types[i]); + + if (ok) { + has_color = true; + break; + } } - if (CustomData_has_layer(&orig_me->vdata, CD_PROP_COLOR)) { - return; + CustomDataLayer *cl; + if (has_color) { + cl = BKE_id_attributes_active_get(&orig_me->id); + if (!ELEM(cl->type, CD_PROP_COLOR, CD_MLOOPCOL, CD_PROP_FLOAT3)) { + cl = NULL; + + /* find a color layer */ + for (int step = 0; !cl && step < 2; step++) { + CustomData *cdata = step ? &orig_me->ldata : &orig_me->vdata; + + for (int i = 0; i < cdata->totlayer; i++) { + if (ELEM(cdata->layers[i].type, CD_PROP_COLOR, CD_MLOOPCOL, CD_PROP_FLOAT3)) { + cl = cdata->layers + i; + break; + } + } + } + } + else { + cl = NULL; /* no need to update active layer */ + } } + else { + CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert); + cl = orig_me->vdata.layers + CustomData_get_layer_index(&orig_me->vdata, CD_PROP_COLOR); - CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert); - BKE_mesh_update_customdata_pointers(orig_me, true); - DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES); + BKE_mesh_update_customdata_pointers(orig_me, true); + } + + if (cl) { + BKE_id_attributes_active_set(&orig_me->id, cl); + DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES); + } } /** \warning Expects a fully evaluated depsgraph. */ @@ -2026,8 +2087,8 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv const bool is_hidden = (face_sets[face_index] < 0); /* Avoid creating and modifying the grid_hidden bitmap if the base mesh face is visible and - * there is not bitmap for the grid. This is because missing grid_hidden implies grid is fully - * visible. */ + * there is not bitmap for the grid. This is because missing grid_hidden implies grid is + * fully visible. */ if (is_hidden) { BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg, i); } @@ -2066,8 +2127,8 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object) object->sculpt->face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); /* NOTE: In theory we could add that on the fly when required by sculpt code. - * But this then requires proper update of depsgraph etc. For now we play safe, optimization is - * always possible later if it's worth it. */ + * But this then requires proper update of depsgraph etc. For now we play safe, optimization + * is always possible later if it's worth it. */ BKE_sculpt_mask_layers_ensure(object, mmd); } @@ -2075,8 +2136,8 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object) BKE_mesh_tessface_clear(mesh); /* We always need to flush updates from depsgraph here, since at the very least - * `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer of - * the mesh. + * `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer + * of the mesh. * * All known potential sources of updates: * - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index ca1fada8c76..0b4b8fa0eed 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -31,6 +31,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "BKE_attribute.h" #include "BKE_ccg.h" #include "BKE_mesh.h" /* for BKE_mesh_calc_normals */ #include "BKE_paint.h" @@ -1258,6 +1259,33 @@ static int pbvh_get_buffers_update_flags(PBVH *UNUSED(pbvh)) return update_flags; } +bool BKE_pbvh_get_color_layer(const Mesh *me, CustomDataLayer **r_cl, AttributeDomain *r_attr) +{ + CustomDataLayer *cl = BKE_id_attributes_active_get((ID *)me); + AttributeDomain domain; + + if (!cl || !ELEM(cl->type, CD_PROP_FLOAT3, CD_PROP_COLOR, CD_MLOOPCOL)) { + return false; + } + + domain = BKE_id_attribute_domain((ID *)me, cl); + + if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) { + return false; + } + + if (cl) { + *r_cl = cl; + *r_attr = domain; + + return true; + } + else { + *r_cl = NULL; + return false; + } +} + static void pbvh_update_draw_buffer_cb(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) @@ -1308,17 +1336,23 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, &pbvh->gridkey, update_flags); break; - case PBVH_FACES: + case PBVH_FACES: { + CustomDataLayer *cl = NULL; + AttributeDomain domain; + + BKE_pbvh_get_color_layer(pbvh->mesh, &cl, &domain); + GPU_pbvh_mesh_buffers_update(node->draw_buffers, pbvh->verts, CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK), - CustomData_get_layer(pbvh->ldata, CD_MLOOPCOL), + cl ? cl->data : NULL, + cl ? cl->type : -1, + cl ? domain : ATTR_DOMAIN_AUTO, CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS), pbvh->face_sets_color_seed, pbvh->face_sets_color_default, - CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR), update_flags); - break; + } break; case PBVH_BMESH: GPU_pbvh_bmesh_buffers_update(node->draw_buffers, pbvh->bm, @@ -1445,7 +1479,9 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag) } if (flag & (PBVH_UpdateColor)) { - /* Do nothing */ + for (int i = 0; i < totnode; i++) { + nodes[i]->flag |= PBVH_UpdateRedraw | PBVH_UpdateDrawBuffers | PBVH_UpdateColor; + } } if (flag & (PBVH_UpdateVisibility)) { @@ -2981,7 +3017,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m vi->mask = NULL; if (pbvh->type == PBVH_FACES) { vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK); - vi->vcol = CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR); } } diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 538634f4c9e..04c0a4ebc79 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -1250,6 +1250,19 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 300, 26)) { + LISTBASE_FOREACH (Brush *, br, &bmain->brushes) { + /* buggy code in wm_toolsystem broke smear in old files, + reset to defaults*/ + if (br->sculpt_tool == SCULPT_TOOL_SMEAR) { + br->alpha = 1.0f; + br->spacing = 5; + br->flag &= ~BRUSH_ALPHA_PRESSURE; + br->flag &= ~BRUSH_SPACE_ATTEN; + br->curve_preset = BRUSH_CURVE_SPHERE; + } + } + } /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index f09c019ef8d..7e374ba016c 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -186,12 +186,7 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, geom = DRW_cache_mesh_surface_vertpaint_get(ob); } else { - if (U.experimental.use_sculpt_vertex_colors) { - geom = DRW_cache_mesh_surface_sculptcolors_get(ob); - } - else { - geom = DRW_cache_mesh_surface_vertpaint_get(ob); - } + geom = DRW_cache_mesh_surface_sculptcolors_get(ob); } } else { @@ -272,15 +267,8 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd, } } else if (color_type == V3D_SHADING_VERTEX_COLOR) { - if (U.experimental.use_sculpt_vertex_colors) { - if ((me == NULL) || !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) { - color_type = V3D_SHADING_OBJECT_COLOR; - } - } - else { - if ((me == NULL) || !CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) { - color_type = V3D_SHADING_OBJECT_COLOR; - } + if ((me == NULL) || !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) { + color_type = V3D_SHADING_OBJECT_COLOR; } } diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 18664498d00..f36d3ab21f9 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -374,10 +374,8 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, type = CD_MTFACE; if (layer == -1) { - if (U.experimental.use_sculpt_vertex_colors) { - layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name); - type = CD_PROP_COLOR; - } + layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name); + type = CD_PROP_COLOR; } if (layer == -1) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc index 2c7770c8e72..21d0dea0537 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc @@ -74,28 +74,26 @@ static void extract_vcol_init(const MeshRenderData *mr, } /* Sculpt Vertex Colors */ - if (U.experimental.use_sculpt_vertex_colors) { - for (int i = 0; i < 8; i++) { - if (svcol_layers & (1 << i)) { - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i); - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - - BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) { - GPU_vertformat_alias_add(&format, "c"); - } - if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) { - GPU_vertformat_alias_add(&format, "ac"); - } - /* Gather number of auto layers. */ - /* We only do `vcols` that are not overridden by `uvs`. */ - if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { - BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); - GPU_vertformat_alias_add(&format, attr_name); - } + for (int i = 0; i < 8; i++) { + if (svcol_layers & (1 << i)) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i); + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + + BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "c"); + } + if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "ac"); + } + /* Gather number of auto layers. */ + /* We only do `vcols` that are not overridden by `uvs`. */ + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); + GPU_vertformat_alias_add(&format, attr_name); } } } @@ -140,7 +138,7 @@ static void extract_vcol_init(const MeshRenderData *mr, } } - if (svcol_layers & (1 << i) && U.experimental.use_sculpt_vertex_colors) { + if (svcol_layers & (1 << i)) { if (mr->extract_type == MR_EXTRACT_BMESH) { int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i); BMIter f_iter; diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 702fd2e375a..bd0bc4c3a11 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -763,9 +763,11 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES brush.sculpt.mask brush.sculpt.multiplane_scrape brush.sculpt.nudge + brush.sculpt.paint brush.sculpt.pinch brush.sculpt.pose brush.sculpt.rotate + brush.sculpt.smear brush.sculpt.scrape brush.sculpt.simplify brush.sculpt.smooth diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index ddd9ca4a98c..ebc26095940 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -919,6 +919,7 @@ DEF_ICON_COLOR(BRUSH_TEXFILL) DEF_ICON_COLOR(BRUSH_TEXMASK) DEF_ICON_COLOR(BRUSH_THUMB) DEF_ICON_COLOR(BRUSH_ROTATE) +DEF_ICON_COLOR(BRUSH_PAINT) /* grease pencil sculpt */ DEF_ICON_COLOR(GPBRUSH_SMOOTH) diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 0a2df655395..adb6497aed6 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -451,7 +451,7 @@ static bool bake_object_check(ViewLayer *view_layer, if (target == R_BAKE_TARGET_VERTEX_COLORS) { MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); - const bool mcol_valid = (mcol != NULL && U.experimental.use_sculpt_vertex_colors); + const bool mcol_valid = (mcol != NULL); MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); if (mloopcol == NULL && !mcol_valid) { BKE_reportf(reports, @@ -937,7 +937,7 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re Mesh *me = ob->data; MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); - const bool mcol_valid = (mcol != NULL && U.experimental.use_sculpt_vertex_colors); + const bool mcol_valid = (mcol != NULL); MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); if (mloopcol == NULL && !mcol_valid) { BKE_report(reports, RPT_ERROR, "No vertex colors layer found to bake to"); @@ -1092,7 +1092,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) { Mesh *me = ob->data; MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); - const bool mcol_valid = (mcol != NULL && U.experimental.use_sculpt_vertex_colors); + const bool mcol_valid = (mcol != NULL); MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); const int num_channels = targets->num_channels; const float *result = targets->result; diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index da627c6b7db..17bd101554a 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -392,7 +392,7 @@ static int hide_show_exec(bContext *C, wmOperator *op) } /* End undo. */ - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); /* Ensure that edges and faces get hidden as well (not used by * sculpt but it looks wrong when entering editmode otherwise). */ diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index e65d6ce2d48..e7e9eb9e509 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -189,7 +189,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); if (nodes) { MEM_freeN(nodes); @@ -723,7 +723,7 @@ static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext) operation->sculpt_gesture_end(C, sgcontext); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(CTX_data_active_object(C)); SCULPT_tag_update_overlays(C); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 7bde864e73f..84f1907fb11 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -46,6 +46,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_attribute.h" #include "BKE_brush.h" #include "BKE_ccg.h" #include "BKE_colortools.h" @@ -154,19 +155,141 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, int index) return NULL; } -const float *SCULPT_vertex_color_get(SculptSession *ss, int index) +bool SCULPT_has_colors(const SculptSession *ss) +{ + return ss->vcol || ss->mcol || ss->f3col; +} + +bool SCULPT_vertex_color_get(SculptSession *ss, int index, float out[4]) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: + if (!(ss->vcol || ss->mcol || ss->f3col)) { + zero_v4(out); + return false; + } + + if (ss->vcol_domain == ATTR_DOMAIN_CORNER) { + zero_v4(out); + + int count = ss->pmap[index].count; + for (int i = 0; i < count; i++) { + MPoly *mp = ss->mpoly + ss->pmap[index].indices[i]; + MLoop *ml = ss->mloop + mp->loopstart; + int li = mp->loopstart; + + for (int j = 0; j < mp->totloop; j++, li++, ml++) { + if (ml->v != index) { + continue; + } + + if (ss->vcol_type == CD_MLOOPCOL) { + MLoopCol *col = ss->mcol + li; + + float tmp[4]; + + rgba_uchar_to_float(tmp, (const char *)col); + add_v4_v4(out, tmp); + } + else if (ss->vcol_type == CD_PROP_FLOAT3) { + add_v3_v3(out, ss->f3col[li]); + out[3] += 1.0f; + } + else { + add_v4_v4(out, ss->vcol[li].color); + } + } + } + + if (count) { + mul_v4_fl(out, 1.0f / (float)count); + } + } + else { + if (ss->vcol_type == CD_MLOOPCOL) { + MLoopCol *col = ss->mcol + index; + + float tmp[4]; + rgba_uchar_to_float(tmp, (const char *)col); + copy_v4_v4(out, tmp); + } + else if (ss->vcol_type == CD_PROP_FLOAT3) { + copy_v3_v3(out, ss->f3col[index]); + out[3] = 1.0f; + } + else { + copy_v4_v4(out, ss->vcol[index].color); + } + } + + return ss->vcol || ss->mcol || ss->f3col; + case PBVH_BMESH: + case PBVH_GRIDS: + break; + } + + return false; +} + +void SCULPT_vertex_color_set(SculptSession *ss, int index, float color[4]) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: - if (ss->vcol) { - return ss->vcol[index].color; + if (!(ss->vcol || ss->mcol || ss->f3col)) { + return; + } + + if (ss->vcol_domain == ATTR_DOMAIN_CORNER) { + int count = ss->pmap[index].count; + for (int i = 0; i < count; i++) { + MPoly *mp = ss->mpoly + ss->pmap[index].indices[i]; + MLoop *ml = ss->mloop + mp->loopstart; + int li = mp->loopstart; + + for (int j = 0; j < mp->totloop; j++, li++, ml++) { + if (ml->v != index) { + continue; + } + + if (ss->vcol_type == CD_MLOOPCOL) { + MLoopCol *col = ss->mcol + li; + + col->r = (unsigned char)(color[0] * 255.0f); + col->g = (unsigned char)(color[1] * 255.0f); + col->b = (unsigned char)(color[2] * 255.0f); + col->a = (unsigned char)(color[3] * 255.0f); + } + else if (ss->vcol_type == CD_PROP_FLOAT3) { + copy_v3_v3(ss->f3col[li], color); + } + else { + copy_v4_v4(ss->vcol[li].color, color); + } + } + } + } + else { + if (ss->vcol_type == CD_MLOOPCOL) { + MLoopCol *col = ss->mcol + index; + + col->r = (unsigned char)(color[0] * 255.0f); + col->g = (unsigned char)(color[1] * 255.0f); + col->b = (unsigned char)(color[2] * 255.0f); + col->a = (unsigned char)(color[3] * 255.0f); + } + else if (ss->vcol_type == CD_PROP_FLOAT3) { + copy_v3_v3(ss->f3col[index], color); + } + else { + copy_v4_v4(ss->vcol[index].color, color); + } } + break; case PBVH_BMESH: case PBVH_GRIDS: break; } - return NULL; } void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3]) @@ -1506,7 +1629,10 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, *vd.mask = orig_data.mask; } else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { - copy_v4_v4(vd.col, orig_data.col); + float col[4]; + SCULPT_vertex_color_get(ss, vd.index, col); + + copy_v4_v4(col, orig_data.col); } if (vd.mvert) { @@ -6584,9 +6710,6 @@ bool SCULPT_mode_poll(bContext *C) bool SCULPT_vertex_colors_poll(bContext *C) { - if (!U.experimental.use_sculpt_vertex_colors) { - return false; - } return SCULPT_mode_poll(C); } @@ -7285,7 +7408,8 @@ static bool sculpt_needs_connectivity_info(const Sculpt *sd, return ((stroke_mode == BRUSH_STROKE_SMOOTH) || (ss && ss->cache && ss->cache->alt_smooth) || (brush->sculpt_tool == SCULPT_TOOL_SMOOTH) || (brush->autosmooth_factor > 0) || ((brush->sculpt_tool == SCULPT_TOOL_MASK) && (brush->mask_tool == BRUSH_MASK_SMOOTH)) || - (brush->sculpt_tool == SCULPT_TOOL_POSE) || + (brush->sculpt_tool == SCULPT_TOOL_POSE) || (brush->sculpt_tool == SCULPT_TOOL_PAINT) || + (brush->sculpt_tool == SCULPT_TOOL_SMEAR) || (brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) || (brush->sculpt_tool == SCULPT_TOOL_SLIDE_RELAX) || (brush->sculpt_tool == SCULPT_TOOL_CLOTH) || (brush->sculpt_tool == SCULPT_TOOL_SMEAR) || @@ -8022,7 +8146,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str SCULPT_cache_free(ss->cache); ss->cache = NULL; - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); if (brush->sculpt_tool == SCULPT_TOOL_MASK) { SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); @@ -8272,7 +8396,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *op) /* Finish undo. */ BM_log_all_added(ss->bm, ss->bm_log); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); break; case PBVH_FACES: @@ -8434,7 +8558,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain, SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob); if (has_undo) { SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); } } else { @@ -8697,15 +8821,25 @@ static int vertex_to_loop_colors_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +bool SCULPT_convert_colors_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + + bool ok = ob && ob->data && ob->type == OB_MESH; + ok = ok && ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_OBJECT); + + return ok; +} + static void SCULPT_OT_vertex_to_loop_colors(wmOperatorType *ot) { /* identifiers */ ot->name = "Sculpt Vertex Color to Vertex Color"; - ot->description = "Copy the Sculpt Vertex Color to a regular color layer"; + ot->description = "Copy to active face corner color attribute"; ot->idname = "SCULPT_OT_vertex_to_loop_colors"; /* api callbacks */ - ot->poll = SCULPT_vertex_colors_poll; + ot->poll = SCULPT_convert_colors_poll; ot->exec = vertex_to_loop_colors_exec; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8764,11 +8898,11 @@ static void SCULPT_OT_loop_to_vertex_colors(wmOperatorType *ot) { /* identifiers */ ot->name = "Vertex Color to Sculpt Vertex Color"; - ot->description = "Copy the active loop color layer to the vertex color"; + ot->description = "Load from active face corner color attribute"; ot->idname = "SCULPT_OT_loop_to_vertex_colors"; /* api callbacks */ - ot->poll = SCULPT_vertex_colors_poll; + ot->poll = SCULPT_convert_colors_poll; ot->exec = loop_to_vertex_colors_exec; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8784,8 +8918,9 @@ static int sculpt_sample_color_invoke(bContext *C, Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; int active_vertex = SCULPT_active_vertex_get(ss); - const float *active_vertex_color = SCULPT_vertex_color_get(ss, active_vertex); - if (!active_vertex_color) { + float active_vertex_color[4]; + + if (!SCULPT_vertex_color_get(ss, active_vertex, active_vertex_color)) { return OPERATOR_CANCELLED; } @@ -9180,7 +9315,9 @@ static bool sculpt_mask_by_color_contiguous_floodfill_cb( SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata) { MaskByColorContiguousFloodFillData *data = userdata; - const float *current_color = SCULPT_vertex_color_get(ss, to_v); + float current_color[4]; + SCULPT_vertex_color_get(ss, to_v, current_color); + float new_vertex_mask = sculpt_mask_by_color_delta_get( current_color, data->initial_color, data->threshold, data->invert); data->new_mask[to_v] = new_vertex_mask; @@ -9219,7 +9356,7 @@ static void sculpt_mask_by_color_contiguous(Object *object, ffd.threshold = threshold; ffd.invert = invert; ffd.new_mask = new_mask; - copy_v3_v3(ffd.initial_color, SCULPT_vertex_color_get(ss, vertex)); + SCULPT_vertex_color_get(ss, vertex, ffd.initial_color); SCULPT_floodfill_execute(ss, &flood, sculpt_mask_by_color_contiguous_floodfill_cb, &ffd); SCULPT_floodfill_free(&flood); @@ -9261,12 +9398,17 @@ static void do_mask_by_color_task_cb(void *__restrict userdata, const float threshold = data->mask_by_color_threshold; const bool invert = data->mask_by_color_invert; const bool preserve_mask = data->mask_by_color_preserve_mask; - const float *active_color = SCULPT_vertex_color_get(ss, data->mask_by_color_vertex); + float active_color[4]; + + SCULPT_vertex_color_get(ss, data->mask_by_color_vertex, active_color); PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + float col[4]; + SCULPT_vertex_color_get(ss, vd.index, col); + const float current_mask = *vd.mask; - const float new_mask = sculpt_mask_by_color_delta_get(active_color, vd.col, threshold, invert); + const float new_mask = sculpt_mask_by_color_delta_get(active_color, col, threshold, invert); *vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask); if (current_mask == *vd.mask) { @@ -9324,7 +9466,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven return OPERATOR_CANCELLED; } - if (!ss->vcol) { + if (!SCULPT_has_colors(ss)) { return OPERATOR_CANCELLED; } @@ -9353,7 +9495,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven } BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index a53a2126af4..1db2dd638f0 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -1519,7 +1519,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { SCULPT_filter_cache_free(ss); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index 188bb0a88eb..9cea7aa3e72 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -123,7 +123,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op)) } MEM_SAFE_FREE(nodes); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); /* Force rebuild of PBVH for better BB placement. */ SCULPT_pbvh_clear(ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c index ae6dcbdbff4..6a179e0f596 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c @@ -290,7 +290,7 @@ void sculpt_dynamic_topology_disable_with_undo(Main *bmain, } SCULPT_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, NULL); if (use_undo) { - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); } } } @@ -310,7 +310,7 @@ static void sculpt_dynamic_topology_enable_with_undo(Main *bmain, SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob); if (use_undo) { SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); } } } diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c index 40874375772..20af95ba3cc 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_expand.c @@ -1144,7 +1144,7 @@ static void sculpt_expand_restore_color_data(SculptSession *ss, ExpandCache *exp PBVHNode *node = nodes[n]; PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { - copy_v4_v4(vd.col, expand_cache->original_colors[vd.index]); + SCULPT_vertex_color_set(ss, vd.index, expand_cache->original_colors[vd.index]); } BKE_pbvh_vertex_iter_end; BKE_pbvh_node_mark_redraw(node); @@ -1208,7 +1208,7 @@ static void sculpt_expand_cancel(bContext *C, wmOperator *UNUSED(op)) sculpt_expand_restore_original_state(C, ob, ss->expand_cache); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); sculpt_expand_cache_free(ss); } @@ -1303,7 +1303,7 @@ static void sculpt_expand_colors_update_task_cb(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_ALL) { float initial_color[4]; - copy_v4_v4(initial_color, vd.col); + SCULPT_vertex_color_get(ss, vd.index, initial_color); const bool enabled = sculpt_expand_state_get(ss, expand_cache, vd.index); float fade; @@ -1330,7 +1330,8 @@ static void sculpt_expand_colors_update_task_cb(void *__restrict userdata, continue; } - copy_v4_v4(vd.col, final_color); + SCULPT_vertex_color_set(ss, vd.index, final_color); + any_changed = true; if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -1386,7 +1387,7 @@ static void sculpt_expand_original_state_store(Object *ob, ExpandCache *expand_c if (expand_cache->target == SCULPT_EXPAND_TARGET_COLORS) { expand_cache->original_colors = MEM_malloc_arrayN(totvert, sizeof(float[4]), "initial colors"); for (int i = 0; i < totvert; i++) { - copy_v4_v4(expand_cache->original_colors[i], SCULPT_vertex_color_get(ss, i)); + SCULPT_vertex_color_get(ss, i, expand_cache->original_colors[i]); } } } @@ -1542,7 +1543,7 @@ static void sculpt_expand_finish(bContext *C) { Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); /* Tag all nodes to redraw to avoid artifacts after the fast partial updates. */ PBVHNode **nodes; diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index bdbdb75732a..027cedf3b01 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -412,7 +412,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) MEM_SAFE_FREE(nodes); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); SCULPT_tag_update_overlays(C); @@ -749,7 +749,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op) break; } - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ SCULPT_visibility_sync_all_face_sets_to_vertices(ob); @@ -939,7 +939,7 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op) /* Sync face sets visibility and vertex visibility. */ SCULPT_visibility_sync_all_face_sets_to_vertices(ob); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); for (int i = 0; i < totnode; i++) { BKE_pbvh_node_mark_update_visibility(nodes[i]); @@ -1365,7 +1365,7 @@ static void sculpt_face_set_edit_modify_face_sets(Object *ob, SCULPT_undo_push_begin(ob, "face set edit"); SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS); sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); face_set_edit_do_post_visibility_updates(ob, nodes, totnode); MEM_freeN(nodes); } @@ -1393,7 +1393,7 @@ static void sculpt_face_set_edit_modify_coordinates(bContext *C, } SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); MEM_freeN(nodes); } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index 4b49bf2cefb..7ebc0630c14 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -197,12 +197,19 @@ static void color_filter_task_cb(void *__restrict userdata, fade = clamp_f(fade, -1.0f, 1.0f); float smooth_color[4]; SCULPT_neighbor_color_average(ss, smooth_color, vd.index); - blend_color_interpolate_float(final_color, vd.col, smooth_color, fade); + + float col[4]; + SCULPT_vertex_color_get(ss, vd.index, col); + + blend_color_interpolate_float(final_color, col, smooth_color, fade); break; } } - copy_v3_v3(vd.col, final_color); + float col[4]; + SCULPT_vertex_color_get(ss, vd.index, col); + + copy_v3_v3(col, final_color); if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -221,7 +228,7 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent float filter_strength = RNA_float_get(op->ptr, "strength"); if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); SCULPT_filter_cache_free(ss); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR); return OPERATOR_FINISHED; @@ -285,7 +292,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent return OPERATOR_CANCELLED; } - if (!ss->vcol) { + if (!SCULPT_has_colors(ss)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c index 10f141e2311..29e5eafc45f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c @@ -255,7 +255,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) MEM_SAFE_FREE(nodes); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); SCULPT_tag_update_overlays(C); @@ -470,7 +470,7 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); ED_region_tag_redraw(region); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 3fc1a7674f7..7abea1ba538 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -615,7 +615,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { SCULPT_filter_cache_free(ss); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 696c3332a2b..5ef62b0dacb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -98,10 +98,14 @@ char SCULPT_mesh_symmetry_xyz_get(Object *object); void SCULPT_vertex_random_access_ensure(struct SculptSession *ss); int SCULPT_vertex_count_get(struct SculptSession *ss); + const float *SCULPT_vertex_co_get(struct SculptSession *ss, int index); void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3]); float SCULPT_vertex_mask_get(struct SculptSession *ss, int index); -const float *SCULPT_vertex_color_get(SculptSession *ss, int index); + +bool SCULPT_vertex_color_get(SculptSession *ss, int index, float out[4]); +void SCULPT_vertex_color_set(SculptSession *ss, int index, float color[4]); +bool SCULPT_has_colors(const SculptSession *ss); const float *SCULPT_vertex_persistent_co_get(SculptSession *ss, int index); void SCULPT_vertex_persistent_normal_get(SculptSession *ss, int index, float no[3]); @@ -1306,8 +1310,8 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType SculptUndoNode *SCULPT_undo_get_node(PBVHNode *node); SculptUndoNode *SCULPT_undo_get_first_node(void); void SCULPT_undo_push_begin(struct Object *ob, const char *name); -void SCULPT_undo_push_end(void); -void SCULPT_undo_push_end_ex(const bool use_nested_undo); +void SCULPT_undo_push_end(struct Object *ob); +void SCULPT_undo_push_end_ex(struct Object *ob, const bool use_nested_undo); void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]); diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c index 9b06b2ee5d5..9f19341df29 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c @@ -98,7 +98,7 @@ static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op) SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK); } SCULPT_filter_cache_free(ss); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); ED_workspace_status_text(C, NULL); } @@ -253,7 +253,7 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * SCULPT_filter_cache_free(ss); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); ED_workspace_status_text(C, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_init.c b/source/blender/editors/sculpt_paint/sculpt_mask_init.c index 0c383cdf035..a3b431bd6ce 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_init.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_init.c @@ -166,7 +166,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) multires_stitch_grids(ob); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask); MEM_SAFE_FREE(nodes); diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c index 936ebb7e8f7..3cfdf6dc710 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c @@ -101,7 +101,11 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata, float smooth_color[4]; SCULPT_neighbor_color_average(ss, smooth_color, vd.index); - blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade); + float col[4]; + + SCULPT_vertex_color_get(ss, vd.index, col); + blend_color_interpolate_float(col, col, smooth_color, fade); + SCULPT_vertex_color_set(ss, vd.index, col); if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -193,9 +197,11 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, /* Final mix over the original color using brush alpha. */ mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha); - IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend); - - CLAMP4(vd.col, 0.0f, 1.0f); + float col[4]; + SCULPT_vertex_color_get(ss, vd.index, col); + IMB_blend_color_float(col, orig_data.col, buffer_color, brush->blend); + CLAMP4(col, 0.0f, 1.0f); + SCULPT_vertex_color_set(ss, vd.index, col); if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -230,7 +236,10 @@ static void do_sample_wet_paint_task_cb(void *__restrict userdata, continue; } - add_v4_v4(swptd->color, vd.col); + float col[4]; + SCULPT_vertex_color_get(ss, vd.index, col); + + add_v4_v4(swptd->color, col); swptd->tot_samples++; } BKE_pbvh_vertex_iter_end; @@ -252,7 +261,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; - if (!ss->vcol) { + if (!SCULPT_has_colors(ss)) { return; } @@ -305,7 +314,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BKE_pbvh_parallel_range_settings(&settings, false, totnode); BLI_task_parallel_range(0, totnode, &data, do_color_smooth_task_cb_exec, &settings); return; } @@ -361,7 +370,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode }; TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BKE_pbvh_parallel_range_settings(&settings, false, totnode); BLI_task_parallel_range(0, totnode, &data, do_paint_brush_task_cb_ex, &settings); } @@ -433,7 +442,10 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata, } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - blend_color_interpolate_float(vd.col, ss->cache->prev_colors[vd.index], interp_color, fade); + float col[4]; + SCULPT_vertex_color_get(ss, vd.index, col); + blend_color_interpolate_float(col, ss->cache->prev_colors[vd.index], interp_color, fade); + SCULPT_vertex_color_set(ss, vd.index, col); if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -451,7 +463,10 @@ static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - copy_v4_v4(ss->cache->prev_colors[vd.index], SCULPT_vertex_color_get(ss, vd.index)); + float tmp[4] = {0}; + + SCULPT_vertex_color_get(ss, vd.index, tmp); + copy_v4_v4(ss->cache->prev_colors[vd.index], tmp); } BKE_pbvh_vertex_iter_end; } @@ -461,7 +476,7 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode Brush *brush = BKE_paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; - if (!ss->vcol) { + if (!SCULPT_has_colors(ss)) { return; } @@ -471,7 +486,10 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode if (!ss->cache->prev_colors) { ss->cache->prev_colors = MEM_callocN(sizeof(float[4]) * totvert, "prev colors"); for (int i = 0; i < totvert; i++) { - copy_v4_v4(ss->cache->prev_colors[i], SCULPT_vertex_color_get(ss, i)); + float tmp[4] = {0}; + + SCULPT_vertex_color_get(ss, i, tmp); + copy_v4_v4(ss->cache->prev_colors[i], tmp); } } } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 38165b7622f..e364a413345 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -197,7 +197,11 @@ void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index SculptVertexNeighborIter ni; SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { - add_v4_v4(avg, SCULPT_vertex_color_get(ss, ni.index)); + float tmp[4] = {0}; + + SCULPT_vertex_color_get(ss, ni.index, tmp); + + add_v4_v4(avg, tmp); total++; } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); @@ -206,7 +210,7 @@ void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index mul_v4_v4fl(result, avg, 1.0f / total); } else { - copy_v4_v4(result, SCULPT_vertex_color_get(ss, index)); + SCULPT_vertex_color_get(ss, index, result); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c index 3c0a591e8a7..d85404ae517 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.c +++ b/source/blender/editors/sculpt_paint/sculpt_transform.c @@ -250,7 +250,7 @@ void ED_sculpt_end_transform(struct bContext *C, Object *ob) * undo system works separate from regular undo and this is require to properly * finish an undo step also when canceling. */ const bool use_nested_undo = true; - SCULPT_undo_push_end_ex(use_nested_undo); + SCULPT_undo_push_end_ex(ob, use_nested_undo); SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); } diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 501a1e53276..a01dcc91d5d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -40,6 +40,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BKE_attribute.h" #include "BKE_ccg.h" #include "BKE_context.h" #include "BKE_customdata.h" @@ -47,6 +48,7 @@ #include "BKE_key.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" #include "BKE_multires.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -109,13 +111,36 @@ * End of dynamic topology and symmetrize in this mode are handled in a special * manner as well. */ +#define NO_ACTIVE_LAYER ATTR_DOMAIN_AUTO + typedef struct UndoSculpt { ListBase nodes; size_t undo_size; } UndoSculpt; +typedef struct SculptAttrRef { + AttributeDomain domain; + int type; + char name[MAX_CUSTOMDATA_LAYER_NAME]; + bool was_set; +} SculptAttrRef; + +typedef struct SculptUndoStep { + UndoStep step; + /* NOTE: will split out into list for multi-object-sculpt-mode. */ + UndoSculpt data; + + // active vcol layer + SculptAttrRef active_attr_start; + SculptAttrRef active_attr_end; + + bContext *C; +} SculptUndoStep; + static UndoSculpt *sculpt_undo_get_nodes(void); +static bool sculpt_attr_ref_equals(SculptAttrRef *a, SculptAttrRef *b); +static void sculpt_save_active_attr(Object *ob, SculptAttrRef *attr); static void update_cb(PBVHNode *node, void *rebuild) { @@ -328,14 +353,25 @@ static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode) Object *ob = OBACT(view_layer); SculptSession *ss = ob->sculpt; + if (!ss->pmap) { + Mesh *me = BKE_object_get_original_mesh(ob); + + BKE_mesh_vert_poly_map_create( + &ss->pmap, &ss->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop); + } + if (unode->maxvert) { /* regular mesh restore */ int *index = unode->index; MVert *mvert = ss->mvert; - MPropCol *vcol = ss->vcol; for (int i = 0; i < unode->totvert; i++) { - copy_v4_v4(vcol[index[i]].color, unode->col[i]); + float tmp[4]; + + SCULPT_vertex_color_get(ss, index[i], tmp); + SCULPT_vertex_color_set(ss, index[i], unode->col[i]); + copy_v4_v4(unode->col[i], tmp); + mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } @@ -859,6 +895,9 @@ static void sculpt_undo_free_list(ListBase *lb) if (unode->co) { MEM_freeN(unode->co); } + if (unode->col) { + MEM_freeN(unode->col); + } if (unode->no) { MEM_freeN(unode->no); } @@ -1033,7 +1072,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt usculpt->undo_size += alloc_size; /* FIXME: Should explain why this is allocated here, to be freed in - * `SCULPT_undo_push_end_ex()`? */ + * `SCULPT_undo_push_end_ex(ob)`? */ alloc_size = sizeof(*unode->no) * (size_t)allvert; unode->no = MEM_callocN(alloc_size, "SculptUndoNode.no"); usculpt->undo_size += alloc_size; @@ -1158,7 +1197,10 @@ static void sculpt_undo_store_color(Object *ob, SculptUndoNode *unode) PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin (ss->pbvh, unode->node, vd, PBVH_ITER_ALL) { - copy_v4_v4(unode->col[vd.i], vd.col); + float col[4]; + SCULPT_vertex_color_get(ss, vd.index, col); + + copy_v4_v4(unode->col[vd.i], col); } BKE_pbvh_vertex_iter_end; } @@ -1378,10 +1420,36 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType return unode; } +static bool sculpt_attr_ref_equals(SculptAttrRef *a, SculptAttrRef *b) +{ + return a->domain == b->domain && a->type == b->type && STREQ(a->name, b->name); +} + +static void sculpt_save_active_attr(Object *ob, SculptAttrRef *attr) +{ + Mesh *me = BKE_object_get_original_mesh(ob); + CustomDataLayer *cl; + + if (ob && me && (cl = BKE_id_attributes_active_get((ID *)me))) { + attr->domain = BKE_id_attribute_domain((ID *)me, cl); + BLI_strncpy(attr->name, cl->name, sizeof(attr->name)); + attr->type = cl->type; + } + else { + attr->domain = NO_ACTIVE_LAYER; + attr->name[0] = 0; + } + + attr->was_set = true; +} + void SCULPT_undo_push_begin(Object *ob, const char *name) { UndoStack *ustack = ED_undo_stack_get(); + SculptUndoStep *us; + if (!ob->sculpt->pmap && ob->sculpt->pbvh && BKE_pbvh_type(ob->sculpt->pbvh) == PBVH_FACES) { + } if (ob != NULL) { /* If possible, we need to tag the object and its geometry data as 'changed in the future' in * the previous undo step if it's a memfile one. */ @@ -1392,15 +1460,20 @@ void SCULPT_undo_push_begin(Object *ob, const char *name) /* Special case, we never read from this. */ bContext *C = NULL; - BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT); + us = (SculptUndoStep *)BKE_undosys_step_push_init_with_type( + ustack, C, name, BKE_UNDOSYS_TYPE_SCULPT); + + if (!us->active_attr_start.was_set) { + sculpt_save_active_attr(ob, &us->active_attr_start); + } } -void SCULPT_undo_push_end(void) +void SCULPT_undo_push_end(Object *ob) { - SCULPT_undo_push_end_ex(false); + SCULPT_undo_push_end_ex(ob, false); } -void SCULPT_undo_push_end_ex(const bool use_nested_undo) +void SCULPT_undo_push_end_ex(struct Object *ob, const bool use_nested_undo) { UndoSculpt *usculpt = sculpt_undo_get_nodes(); SculptUndoNode *unode; @@ -1424,28 +1497,53 @@ void SCULPT_undo_push_end_ex(const bool use_nested_undo) } WM_file_tag_modified(); } + + UndoStack *ustack = ED_undo_stack_get(); + SculptUndoStep *us = (SculptUndoStep *)BKE_undosys_stack_init_or_active_with_type( + ustack, BKE_UNDOSYS_TYPE_SCULPT); + + sculpt_save_active_attr(ob, &us->active_attr_end); } /* -------------------------------------------------------------------- */ /** \name Implements ED Undo System * \{ */ -typedef struct SculptUndoStep { - UndoStep step; - /* NOTE: will split out into list for multi-object-sculpt-mode. */ - UndoSculpt data; -} SculptUndoStep; +static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr) +{ + Object *ob = CTX_data_active_object(C); + Mesh *me = BKE_object_get_original_mesh(ob); + + if (attr->domain == NO_ACTIVE_LAYER) { + // from reading the code, it appears you cannot set + // the active layer to NULL, so don't worry about it. + // BKE_id_attributes_active_set(&me->id, NULL); + return; + } -static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p) + SculptAttrRef existing; + sculpt_save_active_attr(ob, &existing); + + if (!sculpt_attr_ref_equals(&existing, attr) && ob->sculpt && ob->sculpt->pbvh) { + BKE_pbvh_update_vertex_data(ob->sculpt->pbvh, PBVH_UpdateColor); + } + + CustomDataLayer *cl; + cl = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain); + + if (cl) { + BKE_id_attributes_active_set(&me->id, cl); + } +} + +static void sculpt_undosys_step_encode_init(struct bContext *C, UndoStep *us_p) { SculptUndoStep *us = (SculptUndoStep *)us_p; /* Dummy, memory is cleared anyway. */ BLI_listbase_clear(&us->data.nodes); } -static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C), - struct Main *bmain, - UndoStep *us_p) +static bool sculpt_undosys_step_encode(struct bContext *C, struct Main *bmain, UndoStep *us_p) { /* Dummy, encoding is done along the way by adding tiles * to the current 'SculptUndoStep' added by encode_init. */ @@ -1472,12 +1570,16 @@ static void sculpt_undosys_step_decode_undo_impl(struct bContext *C, BLI_assert(us->step.is_applied == true); sculpt_undo_restore_list(C, depsgraph, &us->data.nodes); us->step.is_applied = false; + + // sculpt_undo_load_vcol_layer(C, us); } static void sculpt_undosys_step_decode_redo_impl(struct bContext *C, Depsgraph *depsgraph, SculptUndoStep *us) { + // sculpt_undo_load_vcol_layer(C, us); + BLI_assert(us->step.is_applied == false); sculpt_undo_restore_list(C, depsgraph, &us->data.nodes); us->step.is_applied = true; @@ -1500,10 +1602,18 @@ static void sculpt_undosys_step_decode_undo(struct bContext *C, while ((us_iter != us) || (!is_final && us_iter == us)) { BLI_assert(us_iter->step.type == us->step.type); /* Previous loop ensures this. */ + + sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start); sculpt_undosys_step_decode_undo_impl(C, depsgraph, us_iter); + // sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start); + if (us_iter == us) { + if (us_iter->step.prev && us_iter->step.prev->type == BKE_UNDOSYS_TYPE_SCULPT) { + sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter->step.prev)->active_attr_end); + } break; } + us_iter = (SculptUndoStep *)us_iter->step.prev; } } @@ -1520,8 +1630,14 @@ static void sculpt_undosys_step_decode_redo(struct bContext *C, us_iter = (SculptUndoStep *)us_iter->step.prev; } while (us_iter && (us_iter->step.is_applied == false)) { + sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_start); sculpt_undosys_step_decode_redo_impl(C, depsgraph, us_iter); + if (us_iter == us) { + sculpt_undo_set_active_layer(C, &((SculptUndoStep *)us_iter)->active_attr_end); + // if (us_iter->step.next && us_iter->step.next->type == BKE_UNDOSYS_TYPE_SCULPT) { + // sculpt_undo_load_vcol_layer(C, (SculptUndoStep *)us_iter->step.next); + //} break; } us_iter = (SculptUndoStep *)us_iter->step.next; @@ -1595,7 +1711,7 @@ void ED_sculpt_undo_geometry_begin(struct Object *ob, const char *name) void ED_sculpt_undo_geometry_end(struct Object *ob) { SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_GEOMETRY); - SCULPT_undo_push_end(); + SCULPT_undo_push_end(ob); } /* Export for ED_undo_sys. */ @@ -1722,7 +1838,7 @@ void ED_sculpt_undo_push_multires_mesh_end(bContext *C, const char *str) SculptUndoNode *geometry_unode = SCULPT_undo_push_node(object, NULL, SCULPT_UNDO_GEOMETRY); geometry_unode->geometry_clear_pbvh = false; - SCULPT_undo_push_end(); + SCULPT_undo_push_end(object); } /** \} */ diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index 4b859de0ac9..a3fd8ab5f4a 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -977,8 +977,7 @@ static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, Pointer if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); - if (U.experimental.use_sculpt_vertex_colors && - RNA_collection_length(&dataptr, "sculpt_vertex_colors")) { + if (RNA_collection_length(&dataptr, "sculpt_vertex_colors")) { uiItemPointerR( layout, ptr, "layer_name", &dataptr, "sculpt_vertex_colors", "", ICON_GROUP_VCOL); } diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index b770bde65fc..eedc3c240f9 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -25,6 +25,8 @@ #include <stddef.h> +#include "BKE_attribute.h" + #ifdef __cplusplus extern "C" { #endif @@ -78,11 +80,12 @@ enum { void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, const struct MVert *mvert, const float *vmask, - const struct MLoopCol *vcol, + const void *vcol_data, + const int vcol_type, + const AttributeDomain vcol_domain, const int *sculpt_face_sets, const int face_sets_color_seed, const int face_sets_color_default, - const struct MPropCol *vtcol, const int update_flags); void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers, diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 43483916236..81d8d073b30 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -41,7 +41,9 @@ #include "DNA_userdef_types.h" #include "BKE_DerivedMesh.h" +#include "BKE_attribute.h" #include "BKE_ccg.h" +#include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_paint.h" #include "BKE_pbvh.h" @@ -208,18 +210,25 @@ static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt, void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, const MVert *mvert, const float *vmask, - const MLoopCol *vcol, + const void *vcol_data, + const int vcol_type, + const AttributeDomain vcol_domain, const int *sculpt_face_sets, const int face_sets_color_seed, const int face_sets_color_default, - const MPropCol *vtcol, const int update_flags) { + const MPropCol *vtcol = vcol_type == CD_PROP_COLOR ? vcol_data : NULL; + const MLoopCol *vcol = vcol_type == CD_MLOOPCOL ? vcol_data : NULL; + const float(*f3col)[3] = vcol_type == CD_PROP_FLOAT3 ? vcol_data : NULL; + + const bool color_loops = vcol_domain == ATTR_DOMAIN_CORNER; + const bool show_vcol = (vtcol || vcol || f3col) && + (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0; + const bool show_mask = vmask && (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; const bool show_face_sets = sculpt_face_sets && (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0; - const bool show_vcol = (vcol || (vtcol && U.experimental.use_sculpt_vertex_colors)) && - (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0; bool empty_mask = true; bool default_face_set = true; @@ -302,16 +311,40 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, /* Vertex Colors. */ if (show_vcol) { ushort scol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - if (vtcol && U.experimental.use_sculpt_vertex_colors) { - scol[0] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[0]); - scol[1] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[1]); - scol[2] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[2]); - scol[3] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[3]); + if (vtcol) { + if (color_loops) { + scol[0] = unit_float_to_ushort_clamp(vtcol[lt->tri[j]].color[0]); + scol[1] = unit_float_to_ushort_clamp(vtcol[lt->tri[j]].color[1]); + scol[2] = unit_float_to_ushort_clamp(vtcol[lt->tri[j]].color[2]); + scol[3] = unit_float_to_ushort_clamp(vtcol[lt->tri[j]].color[3]); + } + else { + scol[0] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[0]); + scol[1] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[1]); + scol[2] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[2]); + scol[3] = unit_float_to_ushort_clamp(vtcol[vtri[j]].color[3]); + } memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol)); } - else { + else if (f3col) { + if (color_loops) { + scol[0] = unit_float_to_ushort_clamp(f3col[lt->tri[j]][0]); + scol[1] = unit_float_to_ushort_clamp(f3col[lt->tri[j]][1]); + scol[2] = unit_float_to_ushort_clamp(f3col[lt->tri[j]][2]); + scol[3] = USHRT_MAX; + } + else { + scol[0] = unit_float_to_ushort_clamp(f3col[vtri[j]][0]); + scol[1] = unit_float_to_ushort_clamp(f3col[vtri[j]][1]); + scol[2] = unit_float_to_ushort_clamp(f3col[vtri[j]][2]); + scol[3] = USHRT_MAX; + } + memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol)); + } + else if (vcol) { const uint loop_index = lt->tri[j]; - const MLoopCol *mcol = &vcol[loop_index]; + const MLoopCol *mcol = vcol + (color_loops ? loop_index : vtri[j]); + scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]); scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]); scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 563c6ea35e0..84f30e513d5 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -6307,10 +6307,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Cycles Debug", "Enable Cycles debugging options for developers"); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop = RNA_def_property(srna, "use_sculpt_vertex_colors", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_vertex_colors", 1); - RNA_def_property_ui_text(prop, "Sculpt Vertex Colors", "Use the new Vertex Painting system"); - prop = RNA_def_property(srna, "use_sculpt_tools_tilt", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_tools_tilt", 1); RNA_def_property_ui_text( diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index e2b2cc58d48..4d670ba8afd 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -369,6 +369,20 @@ static void face_corner_panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(layout, ptr, "loop_mapping", 0, IFACE_("Mapping"), ICON_NONE); } +static void vert_propcol_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, NULL); + + uiLayoutSetPropSep(layout, true); + + uiLayoutSetActive(layout, RNA_enum_get(ptr, "data_types_verts") & DT_TYPE_PROPCOL); + + uiItemR(layout, ptr, "layers_propcol_select_src", 0, IFACE_("Layer Selection"), ICON_NONE); + uiItemR(layout, ptr, "layers_propcol_select_dst", 0, IFACE_("Layer Mapping"), ICON_NONE); +} + static void face_corner_vcol_panel_draw(const bContext *UNUSED(C), Panel *panel) { uiLayout *layout = panel->layout; @@ -450,6 +464,9 @@ static void panelRegister(ARegionType *region_type) region_type, "vertex_vgroup", "Vertex Groups", NULL, vertex_vgroup_panel_draw, vertex_panel); modifier_subpanel_register( + region_type, "vert_propcol", "Sculpt Colors", NULL, vert_propcol_panel_draw, vertex_panel); + + modifier_subpanel_register( region_type, "edge", "", edge_panel_draw_header, edge_panel_draw, panel_type); PanelType *face_corner_panel = modifier_subpanel_register(region_type, diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c index 40576b68dd5..b48473b6070 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c +++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c @@ -39,11 +39,7 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat, GPUNodeStack *out) { NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage; - if (U.experimental.use_sculpt_vertex_colors) { - GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_PROP_COLOR, vertexColor->layer_name); - return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink); - } - GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_MCOL, vertexColor->layer_name); + GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_PROP_COLOR, vertexColor->layer_name); return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink); } diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index 5eaf026191f..ca54895bb81 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -31,6 +31,7 @@ #include "BLI_utildefines.h" #include "DNA_ID.h" +#include "DNA_brush_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_space_types.h" @@ -211,6 +212,12 @@ static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tre } else { brush = BKE_brush_add(bmain, items[i].name, paint->runtime.ob_mode); + + if (paint->runtime.ob_mode == OB_MODE_SCULPT) { + brush->sculpt_tool = slot_index; + BKE_brush_sculpt_reset(brush); + } + BKE_brush_tool_set(brush, paint, slot_index); } BKE_paint_brush_set(paint, brush); diff --git a/source/tools b/source/tools -Subproject c8579c5cf43229843df505da9644b5b0b720197 +Subproject 548055f40213c775a6b77025525c91e8466e70d |