[Bf-blender-cvs] [42e2398] master: Vertex paint color operations

Campbell Barton noreply at git.blender.org
Thu Jun 16 17:59:02 CEST 2016


Commit: 42e2398ae35da2b499d18ea589767108bd093687
Author: Campbell Barton
Date:   Fri Jun 17 01:45:40 2016 +1000
Branches: master
https://developer.blender.org/rB42e2398ae35da2b499d18ea589767108bd093687

Vertex paint color operations

D2050 by @metaraptor with edits

Adds levels, brightness/contrast, hsv & invert operations.

===================================================================

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/editors/sculpt_paint/paint_intern.h
M	source/blender/editors/sculpt_paint/paint_ops.c
M	source/blender/editors/sculpt_paint/paint_vertex.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index e8d3329..b88b831 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1726,6 +1726,13 @@ class VIEW3D_MT_paint_vertex(Menu):
         layout.operator("paint.vertex_color_smooth")
         layout.operator("paint.vertex_color_dirt")
 
+        layout.separator()
+
+        layout.operator("paint.vertex_color_invert", text="Invert")
+        layout.operator("paint.vertex_color_levels", text="Levels")
+        layout.operator("paint.vertex_color_hsv", text="Hue Saturation Value")
+        layout.operator("paint.vertex_color_brightness_contrast", text="Bright/Contrast")
+
 
 class VIEW3D_MT_hook(Menu):
     bl_label = "Hooks"
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index b6a7d67..7e05ab9 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -101,6 +101,10 @@ bool ED_wpaint_fill(struct VPaint *wp, struct Object *ob, float paintweight);
 
 bool ED_vpaint_smooth(struct Object *ob);
 
+typedef void (*VPaintTransform_Callback)(const float col[3], const void *user_data, float r_col[3]);
+
+bool ED_vpaint_color_transform(struct Object *ob, VPaintTransform_Callback vpaint_tx_fn, const void *user_data);
+
 void PAINT_OT_weight_paint_toggle(struct wmOperatorType *ot);
 void PAINT_OT_weight_paint(struct wmOperatorType *ot);
 void PAINT_OT_weight_set(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index da7667c..bf92341 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -315,6 +315,241 @@ static void PAINT_OT_vertex_color_smooth(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+
+/** \name Vertex Color Transformations
+ * \{ */
+
+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)) {
+		ED_region_tag_redraw(CTX_wm_region(C));
+		return OPERATOR_FINISHED;
+	}
+	else {
+		return OPERATOR_CANCELLED;
+	}
+}
+
+static 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)) {
+		ED_region_tag_redraw(CTX_wm_region(C));
+		return OPERATOR_FINISHED;
+	}
+	else {
+		return OPERATOR_CANCELLED;
+	}
+}
+
+static 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)) {
+		ED_region_tag_redraw(CTX_wm_region(C));
+		return OPERATOR_FINISHED;
+	}
+	else {
+		return OPERATOR_CANCELLED;
+	}
+}
+
+static 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)) {
+		ED_region_tag_redraw(CTX_wm_region(C));
+		return OPERATOR_FINISHED;
+	}
+	else {
+		return OPERATOR_CANCELLED;
+	}
+}
+
+static 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);
+}
+
+/** \} */
+
+
 static int brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	Paint *paint = BKE_paint_get_active_from_context(C);
@@ -1112,6 +1347,11 @@ void ED_operatortypes_paint(void)
 	WM_operatortype_append(PAINT_OT_vertex_color_set);
 	WM_operatortype_append(PAINT_OT_vertex_color_smooth);
 
+	WM_operatortype_append(PAINT_OT_vertex_color_brightness_contrast);
+	WM_operatortype_append(PAINT_OT_vertex_color_hsv);
+	WM_operatortype_append(PAINT_OT_vertex_color_invert);
+	WM_operatortype_append(PAINT_OT_vertex_color_levels);
+
 	/* face-select */
 	WM_operatortype_append(PAINT_OT_face_select_linked);
 	WM_operatortype_append(PAINT_OT_face_select_linked_pick);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 2a1e770..8785587 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -502,6 +502,51 @@ bool ED_vpaint_smooth(Object *ob)
 	return true;
 }
 
+/**
+ * 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)
+{
+	Mesh *me;
+	const MPoly *mp;
+
+	if (((me = BKE_mesh_from_object(ob)) == NULL) ||
+	    (me->mloopcol == NULL && (make_vertexcol(ob) == false)))
+	{
+		return false;
+	}
+
+	const bool do_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+	mp = me->mpoly;
+
+	for (int i = 0; i < me->totpoly; i++, mp++) {
+		MLoopCol *lcol = &me->mloopcol[mp->loopstart];
+
+		if (do_face_sel && !(mp->flag & ME_FACE_SEL)) {
+			continue;
+		}
+
+		for (int j = 0; j < mp->totloop; j++, lcol++) {
+			float col[3];
+			rgb_uchar_to_float(col, &lcol->r);
+
+			vpaint_tx_fn(col, user_data, col);
+
+			rgb_float_to_uchar(&lcol->r, col);
+		}
+	}
+
+	/* remove stale me->mcol, will be added later */
+	BKE_mesh_tessface_clear(me);
+
+	DAG_id_tag_update(&me->id, 0);
+
+	return true;
+}
+
 /* XXX: should be re-implemented as a vertex/weight paint 'color correct' operator */
 #if 0
 void vpaint_dogamma(Scene *scene)




More information about the Bf-blender-cvs mailing list