[Bf-blender-cvs] [7ae4c3a0192] master: Add eyedropper to color-ramp widget

Ray Molenkamp noreply at git.blender.org
Tue Dec 12 03:10:52 CET 2017


Commit: 7ae4c3a01923cccfa372072b880507c58557f45a
Author: Ray Molenkamp
Date:   Tue Dec 12 10:19:55 2017 +1100
Branches: master
https://developer.blender.org/rB7ae4c3a01923cccfa372072b880507c58557f45a

Add eyedropper to color-ramp widget

D2886 by @LazyDodo with edit's by @campbellbarton

The line drawn with the eyedropper is used to fill the color-ramp.

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

M	source/blender/blenkernel/BKE_colorband.h
M	source/blender/blenkernel/intern/colorband.c
M	source/blender/editors/interface/interface_eyedropper.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_ops.c
M	source/blender/editors/interface/interface_templates.c

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

diff --git a/source/blender/blenkernel/BKE_colorband.h b/source/blender/blenkernel/BKE_colorband.h
index aa64e793331..6841d94d360 100644
--- a/source/blender/blenkernel/BKE_colorband.h
+++ b/source/blender/blenkernel/BKE_colorband.h
@@ -36,6 +36,8 @@ struct ColorBand;
 #define MAXCOLORBAND 32
 
 void              BKE_colorband_init(struct ColorBand *coba, bool rangetype);
+void              BKE_colorband_init_from_table_rgba(
+        struct ColorBand *coba, const float (*array)[4], const int array_len);
 struct ColorBand *BKE_colorband_add(bool rangetype);
 bool              BKE_colorband_evaluate(const struct ColorBand *coba, float in, float out[4]);
 void              BKE_colorband_evaluate_table_rgba(const struct ColorBand *coba, float **array, int *size);
diff --git a/source/blender/blenkernel/intern/colorband.c b/source/blender/blenkernel/intern/colorband.c
index a9f4ae083d0..bd02676015e 100644
--- a/source/blender/blenkernel/intern/colorband.c
+++ b/source/blender/blenkernel/intern/colorband.c
@@ -80,6 +80,71 @@ void BKE_colorband_init(ColorBand *coba, bool rangetype)
 	coba->color_mode = COLBAND_BLEND_RGB;
 }
 
+static void colorband_init_from_table_rgba_simple(
+        ColorBand *coba,
+        const float (*array)[4], const int array_len)
+{
+	/* No Re-sample, just de-duplicate. */
+	const float eps = (1.0f / 255.0f) + 1e-6f;
+	BLI_assert(array_len < MAXCOLORBAND);
+	int stops = min_ii(MAXCOLORBAND, array_len);
+	if (stops) {
+		const float step_size = 1.0f / (float)max_ii(stops - 1, 1);
+		int i_curr = -1;
+		for (int i_step = 0; i_step < stops; i_step++) {
+			if ((i_curr != -1) && compare_v4v4(&coba->data[i_curr].r, array[i_step], eps)) {
+				continue;
+			}
+			i_curr += 1;
+			copy_v4_v4(&coba->data[i_curr].r, array[i_step]);
+			coba->data[i_curr].pos = i_step * step_size;
+			coba->data[i_curr].cur = i_curr;
+		}
+		coba->tot = i_curr + 1;
+		coba->cur = 0;
+	}
+	else {
+		/* coba is empty, set 1 black stop */
+		zero_v3(&coba->data[0].r);
+		coba->data[0].a = 1.0f;
+		coba->cur = 0;
+		coba->tot = 1;
+	}
+}
+
+static void colorband_init_from_table_rgba_resample(
+        ColorBand *coba,
+        const float (*array)[4], const int array_len)
+{
+	/* TODO: more optimal method of color simplification,
+	 * for now just pick evenly spaced colors. */
+	BLI_assert(array_len >= MAXCOLORBAND);
+	float step = array_len / (float)MAXCOLORBAND;
+	float color_step = 1.0f / (MAXCOLORBAND - 1);
+	for (int i = 0; i < MAXCOLORBAND; i++) {
+		int cur_color = (int)(step * i);
+		copy_v4_v4(&coba->data[i].r, array[cur_color]);
+		coba->data[i].pos = i * color_step;
+		coba->data[i].cur = i;
+	}
+	coba->tot = MAXCOLORBAND;
+	coba->cur = 0;
+}
+
+void BKE_colorband_init_from_table_rgba(
+        ColorBand *coba,
+        const float (*array)[4], const int array_len)
+{
+	if (array_len < MAXCOLORBAND) {
+		/* No Re-sample, just de-duplicate. */
+		colorband_init_from_table_rgba_simple(coba, array, array_len);
+	}
+	else {
+		/* Re-sample */
+		colorband_init_from_table_rgba_resample(coba, array, array_len);
+	}
+}
+
 ColorBand *BKE_colorband_add(bool rangetype)
 {
 	ColorBand *coba;
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 564b29d3343..9cf40c07c0d 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -74,6 +74,9 @@
 /* for Driver eyedropper */
 #include "ED_keyframing.h"
 
+/* for colorband eyedropper*/
+#include "BLI_bitmap_draw_2d.h"
+#include "BKE_colorband.h"
 
 /* -------------------------------------------------------------------- */
 /* Keymap
@@ -88,6 +91,16 @@ enum {
 	EYE_MODAL_SAMPLE_RESET,
 };
 
+/* Color-band point sample. */
+enum {
+	EYE_MODAL_POINT_CANCEL = 1,
+	EYE_MODAL_POINT_SAMPLE,
+	EYE_MODAL_POINT_CONFIRM,
+	EYE_MODAL_POINT_RESET,
+	EYE_MODAL_POINT_REMOVE_LAST,
+};
+
+
 wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf)
 {
 	static const EnumPropertyItem modal_items[] = {
@@ -116,6 +129,7 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf)
 	WM_modalkeymap_add_item(keymap, SPACEKEY, KM_RELEASE, KM_ANY, 0, EYE_MODAL_SAMPLE_RESET);
 
 	/* assign to operators */
+	WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorband");
 	WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_color");
 	WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_id");
 	WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_depth");
@@ -124,6 +138,37 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf)
 	return keymap;
 }
 
+wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf)
+{
+	static const EnumPropertyItem modal_items_point[] = {
+		{EYE_MODAL_POINT_CANCEL, "CANCEL", 0, "Cancel", ""},
+		{EYE_MODAL_POINT_SAMPLE, "SAMPLE_SAMPLE", 0, "Sample a point", ""},
+		{EYE_MODAL_POINT_CONFIRM, "SAMPLE_CONFIRM", 0, "Confirm Sampling", ""},
+		{EYE_MODAL_POINT_RESET, "SAMPLE_RESET", 0, "Reset Sampling", ""},
+		{0, NULL, 0, NULL, NULL}
+	};
+
+	wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Eyedropper ColorBand PointSampling Map");
+	if (keymap && keymap->modal_items)
+		return keymap;
+
+	keymap = WM_modalkeymap_add(keyconf, "Eyedropper ColorBand PointSampling Map", modal_items_point);
+
+	/* items for modal map */
+	WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, EYE_MODAL_CANCEL);
+	WM_modalkeymap_add_item(keymap, BACKSPACEKEY, KM_PRESS, KM_ANY, 0, EYE_MODAL_POINT_REMOVE_LAST);
+	WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, EYE_MODAL_POINT_CONFIRM);
+	WM_modalkeymap_add_item(keymap, RETKEY, KM_RELEASE, KM_ANY, 0, EYE_MODAL_POINT_CONFIRM);
+	WM_modalkeymap_add_item(keymap, PADENTER, KM_RELEASE, KM_ANY, 0, EYE_MODAL_POINT_CONFIRM);
+	WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, EYE_MODAL_POINT_SAMPLE);
+	WM_modalkeymap_add_item(keymap, SPACEKEY, KM_RELEASE, KM_ANY, 0, EYE_MODAL_POINT_RESET);
+
+	/* assign to operators */
+	WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorband_point");
+
+	return keymap;
+}
+
 /** \} */
 
 
@@ -260,7 +305,7 @@ static void eyedropper_exit(bContext *C, wmOperator *op)
  *
  * Special check for image or nodes where we MAY have HDR pixels which don't display.
  */
-static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3])
+static void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
 {
 
 	/* we could use some clever */
@@ -350,14 +395,14 @@ static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye)
 static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my)
 {
 	float col[3];
-	eyedropper_color_sample_fl(C, eye, mx, my, col);
+	eyedropper_color_sample_fl(C, mx, my, col);
 	eyedropper_color_set(C, eye, col);
 }
 
 static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, int my)
 {
 	float col[3];
-	eyedropper_color_sample_fl(C, eye, mx, my, col);
+	eyedropper_color_sample_fl(C, mx, my, col);
 	/* delay linear conversion */
 	add_v3_v3(eye->accum_col, col);
 	eye->accum_tot++;
@@ -490,6 +535,284 @@ void UI_OT_eyedropper_color(wmOperatorType *ot)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Eyedropper (RGB Color Band)
+ *
+ * Operates by either:
+ * - Dragging a straight line, sampling pixels formed by the line to extract a gradient.
+ * - Clicking on points, adding each color to the end of the color-band.
+ * \{ */
+
+typedef struct Colorband_RNAUpdateCb {
+	PointerRNA ptr;
+	PropertyRNA *prop;
+} Colorband_RNAUpdateCb;
+
+typedef struct EyedropperColorband {
+	int last_x, last_y;
+	/* Alpha is currently fixed at 1.0, may support in future. */
+	float (*color_buffer)[4];
+	int     color_buffer_alloc;
+	int     color_buffer_len;
+	bool sample_start;
+	ColorBand init_color_band;
+	ColorBand *color_band;
+	PointerRNA ptr;
+	PropertyRNA *prop;
+} EyedropperColorband;
+
+/* For user-data only. */
+struct EyedropperColorband_Context {
+	bContext *context;
+	EyedropperColorband *eye;
+};
+
+static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
+{
+	ColorBand *band = NULL;
+	EyedropperColorband *eye;
+
+	uiBut *but = UI_context_active_but_get(C);
+
+	if (but == NULL) {
+		/* pass */
+	}
+	else if (but->type == UI_BTYPE_COLORBAND) {
+		/* When invoked with a hotkey, we can find the band in 'but->poin'. */
+		band = (ColorBand *)but->poin;
+	}
+	else {
+		/* When invoked from a button it's in custom_data field. */
+		band = (ColorBand *)but->custom_data;
+	}
+
+	if (!band)
+		return false;
+
+	op->customdata = eye = MEM_callocN(sizeof(EyedropperColorband), __func__);
+	eye->color_buffer_alloc = 16;
+	eye->color_buffer = MEM_mallocN(sizeof(*eye->color_buffer) * eye->color_buffer_alloc, __func__);
+	eye->color_buffer_len = 0;
+	eye->color_band = band;
+	eye->init_color_band = *eye->color_band;
+	eye->ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
+	eye->prop  = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
+
+	return true;
+}
+
+static void eyedropper_colorband_sample_point(bContext *C, EyedropperColorband *eye, int mx, int my)
+{
+	if (eye->last_x != mx || eye->last_y != my) {
+		float col[4];
+		col[3] = 1.0f;  /* TODO: sample alpha */
+		eyedropper_color_sample_fl(C, mx, my, col);
+		if (eye->color_buffer_len + 1 == eye->color_buffer_alloc) {
+			eye->color_buffer_alloc *= 2;
+			eye->color_buffer = MEM_reallocN(eye->color_buffer, sizeof(*eye->color_buffer) * eye->color_buffer_alloc);
+		}
+		copy_v4_v4(eye->color_buffer[eye->color_buffer_len], col);
+		eye->color_buffer_len += 1;
+		eye->last_x = mx;
+		eye->last_y = my;
+	}
+}
+
+static bool eyedropper_colorband_sample_callback(int mx, int my, void *userdata)
+{
+	struct EyedropperColorband_Context *data = userdata;
+	bContext *C = data->context;
+	EyedropperColorband *eye = data->eye;
+	eyedropper_colorband_sample_point(C, eye, mx, my);
+	return true;
+}
+
+static void eyedropper_colorband_sample_segment(bContext *C, EyedropperColorband *eye, int mx, int my)
+{
+	/* Since the mouse tends to move rather rapidly we use #BLI_bitmap_draw_2d_line_v2v2i
+	 * to interpolate between the reported coordinates */
+	struct EyedropperColorband_Context u

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list