temp-sculpt-colors: commit patch

This commit is contained in:
Joseph Eagar 2021-11-03 12:15:13 -07:00
parent 6cf734a2e5
commit 1dcc741f43
48 changed files with 659 additions and 244 deletions

@ -1 +1 @@
Subproject commit 62e82958a760dad775d9b3387d7fb535fd6de4c6
Subproject commit 326997b913d04bc5bc4656973d1e1a819f860dd2

@ -1 +1 @@
Subproject commit 4475cbd11a636382d57571e0f5dfeff1f90bd6b7
Subproject commit 59c8409947c4174983a36ec28dfeda2be9e254d2

@ -1 +1 @@
Subproject commit 788441f2930465bbfba8f0797b12dcef1d46694d
Subproject commit 98f6085e9d71ba35d41e5aafbcb7981bd7c48275

View File

@ -461,44 +461,6 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
col.operator("mesh.vertex_color_add", icon='ADD', text="")
col.operator("mesh.vertex_color_remove", icon='REMOVE', text="")
class DATA_PT_sculpt_vertex_colors(MeshButtonsPanel, Panel):
bl_label = "Sculpt Vertex Colors"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
return super().poll(context) and context.preferences.experimental.use_sculpt_vertex_colors
def draw(self, context):
layout = self.layout
me = context.mesh
row = layout.row()
col = row.column()
col.template_list(
"MESH_UL_vcols",
"svcols",
me,
"sculpt_vertex_colors",
me.sculpt_vertex_colors,
"active_index",
rows=2,
)
col = row.column(align=True)
col.operator("mesh.sculpt_vertex_color_add", icon='ADD', text="")
col.operator("mesh.sculpt_vertex_color_remove", icon='REMOVE', text="")
row = layout.row()
col = row.column()
col.operator("sculpt.vertex_to_loop_colors", text="Store Sculpt Vertex Color")
col.operator("sculpt.loop_to_vertex_colors", text="Load Sculpt Vertex Color")
class DATA_PT_remesh(MeshButtonsPanel, Panel):
bl_label = "Remesh"
bl_options = {'DEFAULT_CLOSED'}
@ -522,8 +484,7 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
if context.preferences.experimental.use_sculpt_vertex_colors:
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
col.operator("object.voxel_remesh", text="Voxel Remesh")
else:
@ -614,6 +575,12 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
col.operator("geometry.attribute_add", icon='ADD', text="")
col.operator("geometry.attribute_remove", icon='REMOVE', text="")
active = mesh.attributes.active
print(active.domain, active.data_type)
if active.domain == "POINT" and active.data_type == "FLOAT_COLOR":
layout.operator("sculpt.vertex_to_loop_colors", text="Save To Corners")
layout.operator("sculpt.loop_to_vertex_colors", text="Load From Corners")
self.draw_attribute_warnings(context, layout)
def draw_attribute_warnings(self, context, layout):
@ -663,7 +630,6 @@ classes = (
DATA_PT_shape_keys,
DATA_PT_uv_texture,
DATA_PT_vertex_colors,
DATA_PT_sculpt_vertex_colors,
DATA_PT_face_maps,
DATA_PT_mesh_attributes,
DATA_PT_normals,

View File

@ -1293,8 +1293,6 @@ class _defs_sculpt:
exclude_filter = {}
# Use 'bpy.context' instead of 'context' since it can be None.
prefs = bpy.context.preferences
if not prefs.experimental.use_sculpt_vertex_colors:
exclude_filter = {'PAINT', 'SMEAR'}
return generate_from_enum_ex(
context,
@ -2851,17 +2849,13 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_sculpt.cloth_filter,
lambda context: (
(_defs_sculpt.color_filter,)
if context is None or (
context.preferences.view.show_developer_ui and
context.preferences.experimental.use_sculpt_vertex_colors)
if context is None
else ()
),
None,
lambda context: (
(_defs_sculpt.mask_by_color,)
if context is None or (
context.preferences.view.show_developer_ui and
context.preferences.experimental.use_sculpt_vertex_colors)
if context is None
else ()
),
None,

View File

@ -2247,7 +2247,6 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
def draw(self, context):
self._draw_items(
context, (
({"property": "use_sculpt_vertex_colors"}, "T71947"),
({"property": "use_sculpt_tools_tilt"}, "T82877"),
({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),

View File

@ -837,8 +837,7 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
if context.preferences.experimental.use_sculpt_vertex_colors:
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
layout.operator("object.voxel_remesh", text="Remesh")

View File

@ -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

View File

@ -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). */

View File

@ -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. */

View File

@ -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
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
BKE_mesh_update_customdata_pointers(orig_me, true);
}
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);
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

View File

@ -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);
}
}

View File

@ -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.
*

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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);
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);
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);
}
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;

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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). */

View File

@ -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);
}

View File

@ -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) {
return ss->vcol[index].color;
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 || 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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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]);

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
static void sculpt_undosys_step_encode_init(struct bContext *UNUSED(C), UndoStep *us_p)
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;
}
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);
}
/** \} */

View File

@ -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);
}

View File

@ -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,

View File

@ -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]);

View File

@ -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(

View File

@ -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;
@ -449,6 +463,9 @@ static void panelRegister(ARegionType *region_type)
modifier_subpanel_register(
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);

View File

@ -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);
}

View File

@ -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);

@ -1 +1 @@
Subproject commit c8579c5cf43229843df505da9644b5b0b7201974
Subproject commit 548055f40213c775a6b77025525c91e8466e70d6