Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py23
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h8
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc393
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_utils.c75
5 files changed, 227 insertions, 273 deletions
diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index 8089a65960c..1a7394e03af 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -4,15 +4,10 @@
# <pep8 compliant>
-def get_vcolor_layer_data(me):
- for lay in me.vertex_colors:
- if lay.active:
- return lay.data
-
- lay = me.vertex_colors.new()
- lay.active = True
- return lay.data
-
+def ensure_active_color_attribute(me):
+ if me.attributes.active_color:
+ return me.attributes.active_color
+ return me.color_attributes.new("Color", 'BYTE_COLOR', 'FACE_CORNER')
def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only, normalize):
from mathutils import Vector
@@ -101,17 +96,21 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
else:
tone_range = 1.0 / tone_range
- active_col_layer = get_vcolor_layer_data(me)
- if not active_col_layer:
+ active_color_attribute = ensure_active_color_attribute(me)
+ if not active_color_attribute:
return {'CANCELLED'}
+ point_domain = active_color_attribute.domain == 'POINT'
+
+ attribute_data = active_color_attribute.data
+
use_paint_mask = me.use_paint_mask
for i, p in enumerate(me.polygons):
if not use_paint_mask or p.select:
for loop_index in p.loop_indices:
loop = me.loops[loop_index]
v = loop.vertex_index
- col = active_col_layer[loop_index].color
+ col = attribute_data[v if point_domain else loop_index].color
tone = vert_tone[v]
tone = (tone - min_tone) * tone_range
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 64517560256..b2a7334a13e 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -50,7 +50,6 @@ set(SRC
paint_utils.c
paint_vertex.cc
paint_vertex_color_ops.cc
- paint_vertex_color_utils.c
paint_vertex_proj.c
paint_vertex_weight_ops.c
paint_vertex_weight_utils.c
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 187f793eefe..e11e6c1850b 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -135,18 +135,10 @@ void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
unsigned int vpaint_get_current_color(struct Scene *scene, struct VPaint *vp, bool secondary);
-/* paint_vertex_color_utils.c */
-
/**
* \note weight-paint has an equivalent function: #ED_wpaint_blend_tool
*/
unsigned int ED_vpaint_blend_tool(int tool, uint col, uint paintcol, int alpha_i);
-/**
- * Apply callback to each vertex of the active vertex color layer.
- */
-bool ED_vpaint_color_transform(struct Object *ob,
- VPaintTransform_Callback vpaint_tx_fn,
- const void *user_data);
/* paint_vertex_weight_utils.c */
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
index 6a47aceb2b0..f5652384177 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
@@ -12,11 +12,15 @@
#include "DNA_scene_types.h"
#include "BLI_array.hh"
+#include "BLI_index_mask_ops.hh"
#include "BLI_math_base.h"
#include "BLI_math_color.h"
+#include "BLI_vector.hh"
+#include "BKE_attribute_math.hh"
#include "BKE_context.h"
#include "BKE_deform.h"
+#include "BKE_geometry_set.hh"
#include "BKE_mesh.h"
#include "DEG_depsgraph.h"
@@ -32,6 +36,10 @@
#include "paint_intern.h" /* own include */
using blender::Array;
+using blender::ColorGeometry4f;
+using blender::GMutableSpan;
+using blender::IndexMask;
+using blender::Vector;
/* -------------------------------------------------------------------- */
/** \name Internal Utility Functions
@@ -62,34 +70,57 @@ static void tag_object_after_update(Object *object)
static bool vertex_paint_from_weight(Object *ob)
{
- Mesh *me;
- const MPoly *mp;
- int vgroup_active;
+ using namespace blender;
+ Mesh *me;
if (((me = BKE_mesh_from_object(ob)) == nullptr ||
(ED_mesh_color_ensure(me, nullptr)) == false)) {
return false;
}
- /* TODO: respect selection. */
- /* TODO: Do we want to take weights from evaluated mesh instead? 2.7x was not doing it anyway. */
- mp = me->mpoly;
- vgroup_active = me->vertex_group_active_index - 1;
- for (int i = 0; i < me->totpoly; i++, mp++) {
- MLoopCol *lcol = &me->mloopcol[mp->loopstart];
- uint j = 0;
- do {
- uint vidx = me->mloop[mp->loopstart + j].v;
- const float weight = BKE_defvert_find_weight(&me->dvert[vidx], vgroup_active);
- const uchar grayscale = weight * 255;
- lcol->r = grayscale;
- lcol->b = grayscale;
- lcol->g = grayscale;
- lcol++;
- j++;
- } while (j < mp->totloop);
+ const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me->id);
+ if (active_color_layer == nullptr) {
+ BLI_assert_unreachable();
+ return false;
+ }
+
+ const int active_vertex_group_index = me->vertex_group_active_index - 1;
+ const bDeformGroup *deform_group = static_cast<const bDeformGroup *>(
+ BLI_findlink(&me->vertex_group_names, active_vertex_group_index));
+ if (deform_group == nullptr) {
+ BLI_assert_unreachable();
+ return false;
+ }
+
+ MeshComponent component;
+ component.replace(me, GeometryOwnershipType::Editable);
+
+ bke::WriteAttributeLookup color_attribute = component.attribute_try_get_for_write(
+ active_color_layer->name);
+ if (!color_attribute) {
+ BLI_assert_unreachable();
+ return false;
+ }
+
+ /* Retrieve the vertex group with the domain and type of the existing color
+ * attribute, in order to let the attribute API handle both conversions. */
+ const GVArray vertex_group = component.attribute_get_for_read(
+ deform_group->name,
+ ATTR_DOMAIN_POINT,
+ bke::cpp_type_to_custom_data_type(color_attribute.varray.type()));
+ if (!vertex_group) {
+ BLI_assert_unreachable();
+ return false;
}
+ GVArray_GSpan interpolated{component.attribute_try_adapt_domain(
+ vertex_group, ATTR_DOMAIN_POINT, color_attribute.domain)};
+
+ color_attribute.varray.set_all(interpolated.data());
+
+ if (color_attribute.tag_modified_fn) {
+ color_attribute.tag_modified_fn();
+ }
tag_object_after_update(ob);
return true;
@@ -128,99 +159,81 @@ void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot)
/** \name Smooth Vertex Colors Operator
* \{ */
-static void vertex_color_smooth_looptag(Mesh *me, const bool *mlooptag)
+static IndexMask get_selected_indices(const Mesh &mesh,
+ const AttributeDomain domain,
+ Vector<int64_t> &indices)
{
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const MPoly *mp;
- bool has_shared = false;
+ using namespace blender;
+ Span<MVert> verts(mesh.mvert, mesh.totvert);
+ Span<MPoly> faces(mesh.mpoly, mesh.totpoly);
+
+ MeshComponent component;
+ component.replace(&const_cast<Mesh &>(mesh), GeometryOwnershipType::ReadOnly);
+
+ if (mesh.editflag & ME_EDIT_PAINT_FACE_SEL) {
+ const VArray<bool> selection = component.attribute_try_adapt_domain(
+ VArray<bool>::ForFunc(faces.size(),
+ [&](const int i) { return faces[i].flag & ME_FACE_SEL; }),
+ ATTR_DOMAIN_FACE,
+ domain);
+
+ return index_mask_ops::find_indices_based_on_predicate(
+ IndexMask(component.attribute_domain_size(domain)), 4096, indices, [&](const int i) {
+ return selection[i];
+ });
+ }
+ if (mesh.editflag & ME_EDIT_PAINT_VERT_SEL) {
+ const VArray<bool> selection = component.attribute_try_adapt_domain(
+ VArray<bool>::ForFunc(verts.size(), [&](const int i) { return verts[i].flag & SELECT; }),
+ ATTR_DOMAIN_POINT,
+ domain);
+
+ return index_mask_ops::find_indices_based_on_predicate(
+ IndexMask(component.attribute_domain_size(domain)), 4096, indices, [&](const int i) {
+ return selection[i];
+ });
+ }
+ return IndexMask(component.attribute_domain_size(domain));
+}
- if (me->mloopcol == nullptr || me->totvert == 0 || me->totpoly == 0) {
+static void face_corner_color_equalize_vertices(Mesh &mesh, const IndexMask selection)
+{
+ using namespace blender;
+
+ const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&mesh.id);
+ if (active_color_layer == nullptr) {
+ BLI_assert_unreachable();
return;
}
- int(*scol)[4] = static_cast<int(*)[4]>(MEM_callocN(sizeof(int) * me->totvert * 5, "scol"));
-
- int i;
- for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
- if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
- const MLoop *ml = me->mloop + mp->loopstart;
- MLoopCol *lcol = me->mloopcol + mp->loopstart;
- for (int j = 0; j < mp->totloop; j++, ml++, lcol++) {
- scol[ml->v][0] += lcol->r;
- scol[ml->v][1] += lcol->g;
- scol[ml->v][2] += lcol->b;
- scol[ml->v][3] += 1;
- has_shared = 1;
- }
- }
+ MeshComponent component;
+ component.replace(&mesh, GeometryOwnershipType::Editable);
+
+ if (component.attribute_get_meta_data(active_color_layer->name)->domain == ATTR_DOMAIN_POINT) {
+ return;
}
- if (has_shared) {
- for (i = 0; i < me->totvert; i++) {
- if (scol[i][3] != 0) {
- scol[i][0] = divide_round_i(scol[i][0], scol[i][3]);
- scol[i][1] = divide_round_i(scol[i][1], scol[i][3]);
- scol[i][2] = divide_round_i(scol[i][2], scol[i][3]);
- }
- }
+ GVArray color_attribute_point = component.attribute_try_get_for_read(active_color_layer->name,
+ ATTR_DOMAIN_POINT);
- for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
- if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
- const MLoop *ml = me->mloop + mp->loopstart;
- MLoopCol *lcol = me->mloopcol + mp->loopstart;
- for (int j = 0; j < mp->totloop; j++, ml++, lcol++) {
- if (mlooptag[mp->loopstart + j]) {
- lcol->r = scol[ml->v][0];
- lcol->g = scol[ml->v][1];
- lcol->b = scol[ml->v][2];
- }
- }
- }
- }
- }
+ GVArray color_attribute_corner = component.attribute_try_adapt_domain(
+ color_attribute_point, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER);
- MEM_freeN(scol);
+ color_attribute_corner.materialize(selection, active_color_layer->data);
}
static bool vertex_color_smooth(Object *ob)
{
Mesh *me;
- const MPoly *mp;
- int i, j;
-
if (((me = BKE_mesh_from_object(ob)) == nullptr) ||
(ED_mesh_color_ensure(me, nullptr) == false)) {
return false;
}
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
-
- Array<bool> loop_tag(me->totloop, false);
-
- /* simply tag loops of selected faces */
- mp = me->mpoly;
- for (i = 0; i < me->totpoly; i++, mp++) {
- const MLoop *ml = me->mloop + mp->loopstart;
-
- if (use_face_sel && !(mp->flag & ME_FACE_SEL)) {
- continue;
- }
-
- j = 0;
- do {
- if (!(use_vert_sel && !(me->mvert[ml->v].flag & SELECT))) {
- loop_tag[mp->loopstart + j] = true;
- }
- ml++;
- j++;
- } while (j < mp->totloop);
- }
-
- /* remove stale me->mcol, will be added later */
- BKE_mesh_tessface_clear(me);
+ Vector<int64_t> indices;
+ const IndexMask selection = get_selected_indices(*me, ATTR_DOMAIN_CORNER, indices);
- vertex_color_smooth_looptag(me, loop_tag.data());
+ face_corner_color_equalize_vertices(*me, selection);
tag_object_after_update(ob);
@@ -258,22 +271,52 @@ void PAINT_OT_vertex_color_smooth(wmOperatorType *ot)
/** \name Vertex Color Transformation Operators
* \{ */
-struct VPaintTx_BrightContrastData {
- /* pre-calculated */
- float gain;
- float offset;
-};
-
-static void vpaint_tx_brightness_contrast(const float col[3],
- const void *user_data,
- float r_col[3])
+template<typename TransformFn>
+static bool transform_active_color(Mesh &mesh, const TransformFn &transform_fn)
{
- const VPaintTx_BrightContrastData *data = static_cast<const VPaintTx_BrightContrastData *>(
- user_data);
+ using namespace blender;
- for (int i = 0; i < 3; i++) {
- r_col[i] = data->gain * col[i] + data->offset;
+ const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&mesh.id);
+ if (active_color_layer == nullptr) {
+ BLI_assert_unreachable();
+ return false;
+ }
+
+ MeshComponent component;
+ component.replace(&mesh, GeometryOwnershipType::Editable);
+
+ bke::WriteAttributeLookup color_attribute = component.attribute_try_get_for_write(
+ active_color_layer->name);
+ if (!color_attribute) {
+ BLI_assert_unreachable();
+ return false;
}
+
+ Vector<int64_t> indices;
+ const IndexMask selection = get_selected_indices(mesh, color_attribute.domain, indices);
+
+ attribute_math::convert_to_static_type(color_attribute.varray.type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ threading::parallel_for(selection.index_range(), 1024, [&](IndexRange range) {
+ for (const int i : selection.slice(range)) {
+ if constexpr (std::is_same_v<T, ColorGeometry4f>) {
+ ColorGeometry4f color = color_attribute.varray.get<ColorGeometry4f>(i);
+ transform_fn(color);
+ color_attribute.varray.set_by_copy(i, &color);
+ }
+ else if constexpr (std::is_same_v<T, ColorGeometry4b>) {
+ ColorGeometry4f color = color_attribute.varray.get<ColorGeometry4b>(i).decode();
+ transform_fn(color);
+ ColorGeometry4b color_encoded = color.encode();
+ color_attribute.varray.set_by_copy(i, &color_encoded);
+ }
+ }
+ });
+ });
+
+ DEG_id_tag_update(&mesh.id, 0);
+
+ return true;
}
static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
@@ -303,15 +346,20 @@ static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
}
}
- VPaintTx_BrightContrastData user_data{};
- user_data.gain = gain;
- user_data.offset = offset;
-
- if (ED_vpaint_color_transform(obact, vpaint_tx_brightness_contrast, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
+ Mesh *me;
+ if (((me = BKE_mesh_from_object(obact)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return OPERATOR_CANCELLED;
}
- return OPERATOR_CANCELLED;
+
+ transform_active_color(*me, [&](ColorGeometry4f &color) {
+ for (int i = 0; i < 3; i++) {
+ color[i] = gain * color[i] + offset;
+ }
+ });
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
@@ -337,45 +385,39 @@ void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
RNA_def_property_ui_range(prop, min, max, 1, 1);
}
-struct VPaintTx_HueSatData {
- float hue;
- float sat;
- float val;
-};
-
-static void vpaint_tx_hsv(const float col[3], const void *user_data, float r_col[3])
+static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
{
- const VPaintTx_HueSatData *data = static_cast<const VPaintTx_HueSatData *>(user_data);
- float hsv[3];
- rgb_to_hsv_v(col, hsv);
+ Object *obact = CTX_data_active_object(C);
- hsv[0] += (data->hue - 0.5f);
- if (hsv[0] > 1.0f) {
- hsv[0] -= 1.0f;
- }
- else if (hsv[0] < 0.0f) {
- hsv[0] += 1.0f;
+ const float hue = RNA_float_get(op->ptr, "h");
+ const float sat = RNA_float_get(op->ptr, "s");
+ const float val = RNA_float_get(op->ptr, "v");
+
+ Mesh *me;
+ if (((me = BKE_mesh_from_object(obact)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return OPERATOR_CANCELLED;
}
- hsv[1] *= data->sat;
- hsv[2] *= data->val;
- hsv_to_rgb_v(hsv, r_col);
-}
+ transform_active_color(*me, [&](ColorGeometry4f &color) {
+ float hsv[3];
+ rgb_to_hsv_v(color, hsv);
-static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
-{
- Object *obact = CTX_data_active_object(C);
+ hsv[0] += (hue - 0.5f);
+ if (hsv[0] > 1.0f) {
+ hsv[0] -= 1.0f;
+ }
+ else if (hsv[0] < 0.0f) {
+ hsv[0] += 1.0f;
+ }
+ hsv[1] *= sat;
+ hsv[2] *= val;
- VPaintTx_HueSatData user_data{};
- user_data.hue = RNA_float_get(op->ptr, "h");
- user_data.sat = RNA_float_get(op->ptr, "s");
- user_data.val = RNA_float_get(op->ptr, "v");
+ hsv_to_rgb_v(hsv, color);
+ });
- if (ED_vpaint_color_transform(obact, vpaint_tx_hsv, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
@@ -398,22 +440,24 @@ void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f);
}
-static void vpaint_tx_invert(const float col[3], const void *UNUSED(user_data), float r_col[3])
-{
- for (int i = 0; i < 3; i++) {
- r_col[i] = 1.0f - col[i];
- }
-}
-
static int vertex_color_invert_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obact = CTX_data_active_object(C);
- if (ED_vpaint_color_transform(obact, vpaint_tx_invert, nullptr)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
+ Mesh *me;
+ if (((me = BKE_mesh_from_object(obact)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return OPERATOR_CANCELLED;
}
- return OPERATOR_CANCELLED;
+
+ transform_active_color(*me, [&](ColorGeometry4f &color) {
+ for (int i = 0; i < 3; i++) {
+ color[i] = 1.0f - color[i];
+ }
+ });
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_color_invert(wmOperatorType *ot)
@@ -431,32 +475,27 @@ void PAINT_OT_vertex_color_invert(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-struct VPaintTx_LevelsData {
- float gain;
- float offset;
-};
-
-static void vpaint_tx_levels(const float col[3], const void *user_data, float r_col[3])
-{
- const VPaintTx_LevelsData *data = static_cast<const VPaintTx_LevelsData *>(user_data);
- for (int i = 0; i < 3; i++) {
- r_col[i] = data->gain * (col[i] + data->offset);
- }
-}
-
static int vertex_color_levels_exec(bContext *C, wmOperator *op)
{
Object *obact = CTX_data_active_object(C);
- VPaintTx_LevelsData user_data{};
- user_data.gain = RNA_float_get(op->ptr, "gain");
- user_data.offset = RNA_float_get(op->ptr, "offset");
+ const float gain = RNA_float_get(op->ptr, "gain");
+ const float offset = RNA_float_get(op->ptr, "offset");
- if (ED_vpaint_color_transform(obact, vpaint_tx_levels, &user_data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
- return OPERATOR_FINISHED;
+ Mesh *me;
+ if (((me = BKE_mesh_from_object(obact)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
+ return OPERATOR_CANCELLED;
}
- return OPERATOR_CANCELLED;
+
+ transform_active_color(*me, [&](ColorGeometry4f &color) {
+ for (int i = 0; i < 3; i++) {
+ color[i] = gain * (color[i] + offset);
+ }
+ });
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+
+ return OPERATOR_FINISHED;
}
void PAINT_OT_vertex_color_levels(wmOperatorType *ot)
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
deleted file mode 100644
index cd099f71ccd..00000000000
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_utils.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/** \file
- * \ingroup edsculpt
- *
- * Intended for use by `paint_vertex.c` & `paint_vertex_color_ops.c`.
- */
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-
-#include "BLI_math_base.h"
-#include "BLI_math_color.h"
-
-#include "IMB_colormanagement.h"
-#include "IMB_imbuf.h"
-
-#include "BKE_context.h"
-#include "BKE_mesh.h"
-
-#include "DEG_depsgraph.h"
-
-#include "ED_mesh.h"
-
-#include "paint_intern.h" /* own include */
-
-#define EPS_SATURATION 0.0005f
-
-bool ED_vpaint_color_transform(struct Object *ob,
- VPaintTransform_Callback vpaint_tx_fn,
- const void *user_data)
-{
- Mesh *me;
- const MPoly *mp;
- int i, j;
-
- if (((me = BKE_mesh_from_object(ob)) == NULL) || (ED_mesh_color_ensure(me, NULL) == false)) {
- return false;
- }
-
- const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
-
- mp = me->mpoly;
- for (i = 0; i < me->totpoly; i++, mp++) {
- MLoopCol *lcol = me->mloopcol + mp->loopstart;
-
- if (use_face_sel && !(mp->flag & ME_FACE_SEL)) {
- continue;
- }
-
- j = 0;
- do {
- uint vidx = me->mloop[mp->loopstart + j].v;
- if (!(use_vert_sel && !(me->mvert[vidx].flag & SELECT))) {
- float col_mix[3];
- rgb_uchar_to_float(col_mix, &lcol->r);
-
- vpaint_tx_fn(col_mix, user_data, col_mix);
-
- rgb_float_to_uchar(&lcol->r, col_mix);
- }
- lcol++;
- j++;
- } while (j < mp->totloop);
- }
-
- /* remove stale me->mcol, will be added later */
- BKE_mesh_tessface_clear(me);
-
- DEG_id_tag_update(&me->id, 0);
-
- return true;
-}