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:
authorCampbell Barton <ideasman42@gmail.com>2017-09-30 04:00:29 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-09-30 04:00:29 +0300
commit18965905d0fdb2dd546d95ce9eaa4653cd1e3b17 (patch)
tree5de29a997602e8107f07d49f1ca2b69309e85229 /source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
parente3fe8128e41bb7c576f02ba234dfabf5c399cb60 (diff)
parente3546a5097b1b30a3c694ce0f6b98c2f7e70510c (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_vertex_color_ops.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.c475
1 files changed, 469 insertions, 6 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
index 3cec9dfc063..32515fa81cb 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c
@@ -27,6 +27,10 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_math_base.h"
+#include "BLI_math_color.h"
#include "BKE_context.h"
#include "BKE_mesh.h"
@@ -34,6 +38,9 @@
#include "DEG_depsgraph.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -50,9 +57,90 @@ static int vertex_weight_paint_mode_poll(bContext *C)
(me && me->totpoly && me->dvert);
}
-static bool vertex_paint_from_weight(bContext *C)
+/* -------------------------------------------------------------------- */
+/** \name Set Vertex Colors Operator
+ * \{ */
+
+static bool vertex_color_set(Object *ob, uint paintcol)
+{
+ 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))) {
+ *(int *)lcol = paintcol;
+ }
+ 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;
+}
+
+static int vertex_color_set_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = CTX_data_active_object(C);
+ unsigned int paintcol = vpaint_get_current_col(scene, scene->toolsettings->vpaint);
+
+ if (vertex_color_set(obact, paintcol)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void PAINT_OT_vertex_color_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Vertex Colors";
+ ot->idname = "PAINT_OT_vertex_color_set";
+ ot->description = "Fill the active vertex color layer with the current paint color";
+
+ /* api callbacks */
+ ot->exec = vertex_color_set_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Vertex Color from Weight Operator
+ * \{ */
+
+static bool vertex_paint_from_weight(Object *ob)
{
- Object *ob = CTX_data_active_object(C);
Mesh *me;
const MPoly *mp;
int vgroup_active;
@@ -69,7 +157,7 @@ static bool vertex_paint_from_weight(bContext *C)
for (int i = 0; i < me->totpoly; i++, mp++) {
MLoopCol *lcol = &me->mloopcol[mp->loopstart];
uint j = 0;
- do{
+ do {
uint vidx = me->mloop[mp->loopstart + j].v;
const float weight = defvert_find_weight(&me->dvert[vidx], vgroup_active);
const uchar grayscale = weight * 255;
@@ -82,16 +170,20 @@ static bool vertex_paint_from_weight(bContext *C)
}
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
return true;
}
static int vertex_paint_from_weight_exec(bContext *C, wmOperator *UNUSED(op))
{
- if (vertex_paint_from_weight(C)) {
+ Object *obact = CTX_data_active_object(C);
+ if (vertex_paint_from_weight(obact)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
return OPERATOR_FINISHED;
}
- return OPERATOR_CANCELLED;
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot)
@@ -110,3 +202,374 @@ void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot)
/* TODO: invert, alpha */
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Smooth Vertex Colors Operator
+ * \{ */
+
+static void vertex_color_smooth_looptag(Mesh *me, bool *mlooptag)
+{
+ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const MPoly *mp;
+ int (*scol)[4];
+ int i, j;
+ bool has_shared = false;
+
+ /* if no mloopcol: do not do */
+ /* if mtexpoly: only the involved faces, otherwise all */
+
+ if (me->mloopcol == NULL || me->totvert == 0 || me->totpoly == 0) return;
+
+ scol = MEM_callocN(sizeof(int) * me->totvert * 5, "scol");
+
+ 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 (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;
+ }
+ }
+ }
+
+ 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]);
+ }
+ }
+
+ 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 (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];
+ }
+ }
+ }
+ }
+ }
+
+ MEM_freeN(scol);
+}
+
+static bool vertex_color_smooth(Object *ob)
+{
+ Mesh *me;
+ const MPoly *mp;
+
+ int i, j;
+
+ bool *mlooptag;
+
+ 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;
+
+ mlooptag = MEM_callocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
+
+ /* simply tag loops of selected faces */
+ mp = me->mpoly;
+ for (i = 0; i < me->totpoly; i++, mp++) {
+ const MLoop *ml = me->mloop + mp->loopstart;
+ int ml_index = mp->loopstart;
+
+ if (use_face_sel && !(mp->flag & ME_FACE_SEL))
+ continue;
+
+ for (j = 0; j < mp->totloop; j++, ml_index++, ml++) {
+ mlooptag[ml_index] = true;
+ }
+ }
+
+ /* remove stale me->mcol, will be added later */
+ BKE_mesh_tessface_clear(me);
+
+ vertex_color_smooth_looptag(me, mlooptag);
+
+ MEM_freeN(mlooptag);
+
+ DEG_id_tag_update(&me->id, 0);
+
+ return true;
+}
+
+
+static int vertex_color_smooth_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obact = CTX_data_active_object(C);
+ if (vertex_color_smooth(obact)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void PAINT_OT_vertex_color_smooth(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Smooth Vertex Colors";
+ ot->idname = "PAINT_OT_vertex_color_smooth";
+ ot->description = "Smooth colors across vertices";
+
+ /* api callbacks */
+ ot->exec = vertex_color_smooth_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \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])
+{
+ const struct VPaintTx_BrightContrastData *data = user_data;
+
+ for (int i = 0; i < 3; i++) {
+ r_col[i] = data->gain * col[i] + data->offset;
+ }
+}
+
+static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ float gain, offset;
+ {
+ float brightness = RNA_float_get(op->ptr, "brightness");
+ float contrast = RNA_float_get(op->ptr, "contrast");
+ brightness /= 100.0f;
+ float delta = contrast / 200.0f;
+ gain = 1.0f - delta * 2.0f;
+ /*
+ * The algorithm is by Werner D. Streidt
+ * (http://visca.com/ffactory/archives/5-99/msg00021.html)
+ * Extracted of OpenCV demhist.c
+ */
+ if (contrast > 0) {
+ gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
+ offset = gain * (brightness - delta);
+ }
+ else {
+ delta *= -1;
+ offset = gain * (brightness + delta);
+ }
+ }
+
+ const struct VPaintTx_BrightContrastData user_data = {
+ .gain = gain,
+ .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;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void PAINT_OT_vertex_color_brightness_contrast(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Vertex Paint Bright/Contrast";
+ ot->idname = "PAINT_OT_vertex_color_brightness_contrast";
+ ot->description = "Adjust vertex color brightness/contrast";
+
+ /* api callbacks */
+ ot->exec = vertex_color_brightness_contrast_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ const float min = -100, max = +100;
+ prop = RNA_def_float(ot->srna, "brightness", 0.0f, min, max, "Brightness", "", min, max);
+ prop = RNA_def_float(ot->srna, "contrast", 0.0f, min, max, "Contrast", "", min, max);
+ 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])
+{
+ const struct VPaintTx_HueSatData *data = user_data;
+ float hsv[3];
+ rgb_to_hsv_v(col, hsv);
+
+ 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;
+ }
+ hsv[1] *= data->sat;
+ hsv[2] *= data->val;
+
+ hsv_to_rgb_v(hsv, r_col);
+}
+
+static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ const struct VPaintTx_HueSatData user_data = {
+ .hue = RNA_float_get(op->ptr, "h"),
+ .sat = RNA_float_get(op->ptr, "s"),
+ .val = RNA_float_get(op->ptr, "v"),
+ };
+
+ if (ED_vpaint_color_transform(obact, vpaint_tx_hsv, &user_data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Paint Hue Saturation Value";
+ ot->idname = "PAINT_OT_vertex_color_hsv";
+ ot->description = "Adjust vertex color HSV values";
+
+ /* api callbacks */
+ ot->exec = vertex_color_hsv_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ RNA_def_float(ot->srna, "h", 0.5f, 0.0f, 1.0f, "Hue", "", 0.0f, 1.0f);
+ RNA_def_float(ot->srna, "s", 1.0f, 0.0f, 2.0f, "Saturation", "", 0.0f, 2.0f);
+ 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, NULL)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void PAINT_OT_vertex_color_invert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Paint Invert";
+ ot->idname = "PAINT_OT_vertex_color_invert";
+ ot->description = "Invert RGB values";
+
+ /* api callbacks */
+ ot->exec = vertex_color_invert_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ 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 struct VPaintTx_LevelsData *data = 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);
+
+ const struct VPaintTx_LevelsData user_data = {
+ .gain = RNA_float_get(op->ptr, "gain"),
+ .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;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void PAINT_OT_vertex_color_levels(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Paint Levels";
+ ot->idname = "PAINT_OT_vertex_color_levels";
+ ot->description = "Adjust levels of vertex colors";
+
+ /* api callbacks */
+ ot->exec = vertex_color_levels_exec;
+ ot->poll = vertex_paint_mode_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* params */
+ RNA_def_float(ot->srna, "offset", 0.0f, -1.0f, 1.0f, "Offset", "Value to add to colors", -1.0f, 1.0f);
+ RNA_def_float(ot->srna, "gain", 1.0f, 0.0f, FLT_MAX, "Gain", "Value to multiply colors by", 0.0f, 10.0f);
+}
+
+/** \} */