[Bf-blender-cvs] [efc4862ee69] blender2.8: Refactor: Copy/Paste values from/to UI

Jacques Lucke noreply at git.blender.org
Thu Sep 27 16:07:18 CEST 2018


Commit: efc4862ee69ca9565c1176c59628e023cdea17d0
Author: Jacques Lucke
Date:   Thu Sep 27 16:06:24 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBefc4862ee69ca9565c1176c59628e023cdea17d0

Refactor: Copy/Paste values from/to UI

Previously copy and paste was handled within the same function using a mode switch, which is quite ugly in most cases.
This patch separates the function into two and splits up those in even smaller functions to increase maintainability.

Finally one new feature was added: You can copy from disabled fields now. (requested by hjalti)

Reviewers: brecht

Differential Revision: https://developer.blender.org/D3738

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

M	source/blender/editors/interface/interface_handlers.c

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

diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 94c9ecb7e38..bff43e5cbaa 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2037,278 +2037,390 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
 
 /* ******************* copy and paste ********************  */
 
-/* c = copy, v = paste */
-static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, const char mode, const bool copy_array)
+static bool ui_but_contains_password(uiBut *but)
 {
-	int buf_paste_len = 0;
-	const char *buf_paste = "";
-	bool buf_paste_alloc = false;
-	bool show_report = false;  /* use to display errors parsing paste input */
+	return but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD);
+}
 
-	BLI_assert((but->flag & UI_BUT_DISABLED) == 0); /* caller should check */
+static void ui_but_get_pasted_text_from_clipboard(char **buf_paste, int *buf_len)
+{
+	char *text;
+	int length;
+	/* get only first line even if the clipboard contains multiple lines */
+	text = WM_clipboard_text_get_firstline(false, &length);
 
-	if (mode == 'c') {
-		/* disallow copying from any passwords */
-		if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) {
-			return;
-		}
+	if (text) {
+		*buf_paste = text;
+		*buf_len = length;
 	}
+	else {
+		*buf_paste = MEM_callocN(sizeof(char), __func__);
+		*buf_len = 0;
+	}
+}
 
-	if (mode == 'v') {
-		/* extract first line from clipboard in case of multi-line copies */
-		const char *buf_paste_test;
+static int get_but_property_array_length(uiBut *but)
+{
+	return RNA_property_array_length(&but->rnapoin, but->rnaprop);
+}
 
-		buf_paste_test = WM_clipboard_text_get_firstline(false, &buf_paste_len);
-		if (buf_paste_test) {
-			buf_paste = buf_paste_test;
-			buf_paste_alloc = true;
-		}
+static void ui_but_set_float_array(bContext *C, uiBut *but, uiHandleButtonData *data, float *values, int array_length)
+{
+	button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+	for (int i = 0; i < array_length; i++) {
+		RNA_property_float_set_index(&but->rnapoin, but->rnaprop, i, values[i]);
 	}
+	if (data) data->value = values[but->rnaindex];
 
-	/* No return from here down */
+	button_activate_state(C, but, BUTTON_STATE_EXIT);
+}
 
+static void float_array_to_string(float *values, int array_length, char *output, int max_output_len)
+{
+	/* to avoid buffer overflow attacks; numbers are quite arbitrary */
+	BLI_assert(max_output_len > 15);
+	max_output_len -= 10;
 
-	/* numeric value */
-	if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) {
+	int current_index = 0;
+	output[current_index] = '[';
+	current_index++;
 
-		if (but->poin == NULL && but->rnapoin.data == NULL) {
-			/* pass */
+	for (int i = 0; i < array_length; i++) {
+		int length = BLI_snprintf(output + current_index, max_output_len - current_index, "%f", values[i]);
+		current_index += length;
+
+		if (i < array_length - 1) {
+			if (current_index < max_output_len) {
+				output[current_index + 0] = ',';
+				output[current_index + 1] = ' ';
+				current_index += 2;
+			}
 		}
-		else if (copy_array && but->rnapoin.data && but->rnaprop &&
-		         ELEM(RNA_property_subtype(but->rnaprop), PROP_COLOR, PROP_TRANSLATION, PROP_DIRECTION,
-		              PROP_VELOCITY, PROP_ACCELERATION, PROP_MATRIX, PROP_EULER, PROP_QUATERNION, PROP_AXISANGLE,
-		              PROP_XYZ, PROP_XYZ_LENGTH, PROP_COLOR_GAMMA, PROP_COORDS))
-		{
-			float values[4];
-			int array_length = RNA_property_array_length(&but->rnapoin, but->rnaprop);
+	}
 
-			if (mode == 'c') {
-				char buf_copy[UI_MAX_DRAW_STR];
+	output[current_index + 0] = ']';
+	output[current_index + 1] = '\0';
+}
 
-				if (array_length == 4) {
-					values[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
-				}
-				else {
-					values[3] = 0.0f;
-				}
-				ui_but_v3_get(but, values);
+static void ui_but_copy_numeric_array(uiBut *but, char *output, int max_output_len)
+{
+	int array_length = get_but_property_array_length(but);
+	float *values = alloca(array_length * sizeof(float));
+	RNA_property_float_get_array(&but->rnapoin, but->rnaprop, values);
+	float_array_to_string(values, array_length, output, max_output_len);
+}
 
-				BLI_snprintf(buf_copy, sizeof(buf_copy), "[%f, %f, %f, %f]", values[0], values[1], values[2], values[3]);
-				WM_clipboard_text_set(buf_copy, 0);
-			}
-			else {
-				if (sscanf(buf_paste, "[%f, %f, %f, %f]", &values[0], &values[1], &values[2], &values[3]) >= array_length) {
-					button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+static bool parse_float_array(char *text, float *values, int expected_length)
+{
+	/* can parse max 4 floats for now */
+	BLI_assert(0 <= expected_length && expected_length <= 4);
 
-					ui_but_v3_set(but, values);
-					if (but->rnaprop && array_length == 4) {
-						RNA_property_float_set_index(&but->rnapoin, but->rnaprop, 3, values[3]);
-					}
-					data->value = values[but->rnaindex];
+	float v[5];
+	int actual_length = sscanf(text, "[%f, %f, %f, %f, %f]", &v[0], &v[1], &v[2], &v[3], &v[4]);
 
-					button_activate_state(C, but, BUTTON_STATE_EXIT);
-				}
-				else {
-					WM_report(RPT_ERROR, "Paste expected 4 numbers, formatted: '[n, n, n, n]'");
-					show_report = true;
-				}
-			}
-		}
-		else if (mode == 'c') {
-			/* Get many decimal places, then strip trailing zeros.
-			 * note: too high values start to give strange results */
-			char buf_copy[UI_MAX_DRAW_STR];
-			ui_but_string_get_ex(but, buf_copy, sizeof(buf_copy), UI_PRECISION_FLOAT_MAX, false, NULL);
-			BLI_str_rstrip_float_zero(buf_copy, '\0');
+	if (actual_length == expected_length) {
+		memcpy(values, v, sizeof(float) * expected_length);
+		return true;
+	}
+	else {
+		return false;
+	}
+}
 
-			WM_clipboard_text_set(buf_copy, 0);
-		}
-		else {
-			double val;
+static void ui_but_paste_numeric_array(bContext *C, uiBut *but, uiHandleButtonData *data, char *buf_paste)
+{
+	int array_length = get_but_property_array_length(but);
+	if (array_length > 4) {
+		// not supported for now
+		return;
+	}
 
-			if (ui_but_string_set_eval_num(C, but, buf_paste, &val)) {
-				button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-				data->value = val;
-				ui_but_string_set(C, but, buf_paste);
-				button_activate_state(C, but, BUTTON_STATE_EXIT);
-			}
-			else {
-				/* evaluating will report errors */
-				show_report = true;
-			}
-		}
+	float *values = alloca(sizeof(float) * array_length);
+
+	if (parse_float_array(buf_paste, values, array_length)) {
+		ui_but_set_float_array(C, but, data, values, array_length);
 	}
+	else {
+		WM_report(RPT_ERROR, "Expected an array of numbers: [n, n, ...]");
+	}
+}
 
-	/* NORMAL button */
-	else if (but->type == UI_BTYPE_UNITVEC) {
-		float xyz[3];
+static void ui_but_copy_numeric_value(uiBut *but, char *output, int max_output_len)
+{
+	/* Get many decimal places, then strip trailing zeros.
+	 * note: too high values start to give strange results */
+	ui_but_string_get_ex(but, output, max_output_len, UI_PRECISION_FLOAT_MAX, false, NULL);
+	BLI_str_rstrip_float_zero(output, '\0');
+}
 
-		if (but->poin == NULL && but->rnapoin.data == NULL) {
-			/* pass */
-		}
-		else if (mode == 'c') {
-			char buf_copy[UI_MAX_DRAW_STR];
-			ui_but_v3_get(but, xyz);
-			BLI_snprintf(buf_copy, sizeof(buf_copy), "[%f, %f, %f]", xyz[0], xyz[1], xyz[2]);
-			WM_clipboard_text_set(buf_copy, 0);
-		}
-		else {
-			if (sscanf(buf_paste, "[%f, %f, %f]", &xyz[0], &xyz[1], &xyz[2]) == 3) {
-				if (normalize_v3(xyz) == 0.0f) {
-					/* better set Z up then have a zero vector */
-					xyz[2] = 1.0;
-				}
-				button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-				ui_but_v3_set(but, xyz);
-				button_activate_state(C, but, BUTTON_STATE_EXIT);
-			}
-			else {
-				WM_report(RPT_ERROR, "Paste expected 3 numbers, formatted: '[n, n, n]'");
-				show_report = true;
-			}
+static void ui_but_paste_numeric_value(bContext *C, uiBut *but, uiHandleButtonData *data, char *buf_paste)
+{
+	double value;
+
+	if (ui_but_string_set_eval_num(C, but, buf_paste, &value)) {
+		button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+		data->value = value;
+		ui_but_string_set(C, but, buf_paste);
+		button_activate_state(C, but, BUTTON_STATE_EXIT);
+	} else {
+		WM_report(RPT_ERROR, "Expected a number");
+	}
+}
+
+static bool ui_but_has_array_value(uiBut *but)
+{
+	return (but->rnapoin.data && but->rnaprop &&
+	        ELEM(RNA_property_subtype(but->rnaprop), PROP_COLOR, PROP_TRANSLATION, PROP_DIRECTION,
+	        PROP_VELOCITY, PROP_ACCELERATION, PROP_MATRIX, PROP_EULER, PROP_QUATERNION, PROP_AXISANGLE,
+	        PROP_XYZ, PROP_XYZ_LENGTH, PROP_COLOR_GAMMA, PROP_COORDS));
+}
+
+static void ui_but_paste_normalized_vector(bContext *C, uiBut *but, char *buf_paste)
+{
+	float xyz[3];
+	if (parse_float_array(buf_paste, xyz, 3)) {
+		if (normalize_v3(xyz) == 0.0f) {
+			/* better set Z up then have a zero vector */
+			xyz[2] = 1.0;
 		}
+		ui_but_set_float_array(C, but, NULL, xyz, 3);
 	}
+	else {
+		WM_report(RPT_ERROR, "Paste expected 3 numbers, formatted: '[n, n, n]'");
+	}
+}
 
+static void ui_but_copy_color(uiBut *but, char *output, int max_output_len)
+{
+	float rgba[4];
 
-	/* RGB triple */
-	else if (but->type == UI_BTYPE_COLOR) {
-		float rgba[4];
+	if (but->rnaprop && get_but_property_array_length(but) == 4)
+		rgba[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
+	else
+		rgba[3] = 1.0f;
 
-		if (but->poin == NULL && but->rnapoin.data == NULL) {
-			/* pass */
+	ui_but_v3_get(but, rgba);
+
+	/* convert to linear color to do compatible copy between gamma and non-gamma */
+	if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
+		srgb_to_linearrgb_v3_v3(rgba, rgba);
+
+	float_array_to_string(rgba, 4, output, max_output_len);
+}
+
+static void ui_but_paste_color(bContext *C, uiBut *but, char *buf_paste)
+{
+	float rgba[4];
+	if (parse_float_array(buf_paste, rgba, 4)) {
+		/* assume linear colors in buffer */
+		if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+			linearrgb_to_srg

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list