[Bf-blender-cvs] [c5d4607] UI-experiments UI-graphical-redesign: Add widget rollover feedback by implementing a Sub-Button pipeline

Julian Eisel noreply at git.blender.org
Mon Jun 8 23:40:47 CEST 2015


Commit: c5d4607792bd15fdfe11af67526979c3ef87fe9a
Author: Julian Eisel
Date:   Mon Jun 8 23:10:01 2015 +0200
Branches: UI-experiments UI-graphical-redesign
https://developer.blender.org/rBc5d4607792bd15fdfe11af67526979c3ef87fe9a

Add widget rollover feedback by implementing a Sub-Button pipeline

As pretty much agreed on in T38070, this implements widget-rollover for
better visual feedback.
The added Sub-Button pipeline should provide us a solid base for future
ideas like using Sub-Buttons to trigger operators (thinking of 'X'-icons
within tabs or menus e.g.), open popups/menus, provide better cursor
feedback, etc. They are basically independent buttons within buttons.

https://developer.blender.org/F187781

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

M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_layout.c
M	source/blender/editors/interface/interface_widgets.c

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

diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index c389642..e4104fd 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -161,6 +161,13 @@ void ui_block_to_window_rctf(const ARegion *ar, uiBlock *block, rctf *rct_dst, c
 	ui_block_to_window_fl(ar, block, &rct_dst->xmax, &rct_dst->ymax);
 }
 
+void ui_block_to_window_rcti(const ARegion *ar, uiBlock *block, rcti *rct_dst, const rcti *rct_src)
+{
+	*rct_dst = *rct_src;
+	ui_block_to_window(ar, block, &rct_dst->xmin, &rct_dst->ymin);
+	ui_block_to_window(ar, block, &rct_dst->xmax, &rct_dst->ymax);
+}
+
 void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y)   /* for mouse cursor */
 {
 	float a, b, c, d, e, f, px, py;
@@ -1323,6 +1330,43 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
 	rect->ymax = floorf(rectf.ymax);
 }
 
+
+/* project a rcti to pixels in regionspace */
+void ui_rcti_to_pixelrect(const ARegion *ar, uiBlock *block, rcti *rct_dst, const rcti *rct_src)
+{
+	rcti rect;
+
+	ui_block_to_window_rcti(ar, block, &rect, rct_src);
+
+	rect.xmin -= ar->winrct.xmin;
+	rect.ymin -= ar->winrct.ymin;
+	rect.xmax -= ar->winrct.xmin;
+	rect.ymax -= ar->winrct.ymin;
+
+	rct_dst->xmin = iroundf(rect.xmin);
+	rct_dst->ymin = iroundf(rect.ymin);
+	rct_dst->xmax = iroundf(rect.xmax);
+	rct_dst->ymax = iroundf(rect.ymax);
+}
+
+/* project a rctf to pixels in regionspace */
+void ui_rctf_to_pixelrect(const ARegion *ar, uiBlock *block, rctf *rct_dst, const rctf *rct_src)
+{
+	rctf rect;
+
+	ui_block_to_window_rctf(ar, block, &rect, rct_src);
+
+	rect.xmin -= ar->winrct.xmin;
+	rect.ymin -= ar->winrct.ymin;
+	rect.xmax -= ar->winrct.xmin;
+	rect.ymax -= ar->winrct.ymin;
+
+	rct_dst->xmin = floorf(rect.xmin);
+	rct_dst->ymin = floorf(rect.ymin);
+	rct_dst->xmax = floorf(rect.xmax);
+	rct_dst->ymax = floorf(rect.ymax);
+}
+
 /* uses local copy of style, to scale things down, and allow widgets to change stuff */
 void UI_block_draw(const bContext *C, uiBlock *block)
 {
@@ -2528,6 +2572,10 @@ static void ui_but_free(const bContext *C, uiBut *but)
 		IMB_freeImBuf((struct ImBuf *)but->poin);
 	}
 
+	if ((BLI_listbase_is_empty(&but->subbuts)) == false) {
+		BLI_freelistN(&but->subbuts);
+	}
+
 	BLI_assert(UI_butstore_is_registered(but->block, but) == false);
 
 	MEM_freeN(but);
@@ -3104,6 +3152,25 @@ void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3])
 	IMB_colormanagement_display_to_scene_linear_v3(pixel, display);
 }
 
+static uiSubBut *ui_def_subbut(
+        uiBut *but, const int type,
+        uiSubButAlign alignment,
+        const int width, const int height)
+{
+	uiSubBut *sbut = MEM_callocN(sizeof(uiSubBut), "uiSubBut");
+
+	sbut->type = type;
+	sbut->align = alignment;
+	sbut->width = width;
+	sbut->height = height;
+
+	/* sbut->rect is calculated later */
+
+	BLI_addtail(&but->subbuts, sbut);
+
+	return sbut;
+}
+
 /**
  * \brief ui_def_but is the function that draws many button types
  *
@@ -3218,6 +3285,13 @@ static uiBut *ui_def_but(
 		}
 	}
 
+	if (but->type == UI_BTYPE_NUM) {
+		const int sbut_width = MIN2(width / 3, height);
+
+		ui_def_subbut(but, UI_SBUT_TYPE_VAL_DECREASE, UI_SBUT_ALIGN_LEFT, sbut_width, height);
+		ui_def_subbut(but, UI_SBUT_TYPE_VAL_INCREASE, UI_SBUT_ALIGN_RIGHT, sbut_width, height);
+	}
+
 	/* keep track of UI_interface.h */
 	if (ELEM(but->type,
 	         UI_BTYPE_BLOCK, UI_BTYPE_BUT, UI_BTYPE_LABEL,
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 016bc7e..5bbbe0c 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -381,6 +381,7 @@ static bool ui_but_contains_pt(uiBut *but, float mx, float my);
 static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y);
 static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit);
 static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event);
+static uiSubBut *ui_subbut_find_mouse_over(const ARegion *ar, const uiBut *but, const int mouse_xy[2]);
 static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type);
 static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
 static void button_activate_exit(
@@ -4235,68 +4236,8 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 	}
 	
 	if (click) {
-		/* we can click on the side arrows to increment/decrement,
-		 * or click inside to edit the value directly */
-		float tempf, softmin, softmax;
-		float handlewidth;
-		int temp;
-
-		softmin = but->softmin;
-		softmax = but->softmax;
-
-		handlewidth = min_ff(BLI_rctf_size_x(&but->rect) / 3, BLI_rctf_size_y(&but->rect));
-
-		if (!ui_but_is_float(but)) {
-			if (mx < (but->rect.xmin + handlewidth)) {
-				button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
-				temp = (int)data->value - 1;
-				if (temp >= softmin && temp <= softmax)
-					data->value = (double)temp;
-				else
-					data->cancel = true;
-
-				button_activate_state(C, but, BUTTON_STATE_EXIT);
-			}
-			else if (mx > (but->rect.xmax - handlewidth)) {
-				button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
-				temp = (int)data->value + 1;
-				if (temp >= softmin && temp <= softmax)
-					data->value = (double)temp;
-				else
-					data->cancel = true;
-
-				button_activate_state(C, but, BUTTON_STATE_EXIT);
-			}
-			else {
-				button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
-			}
-		}
-		else {
-			if (mx < (but->rect.xmin + handlewidth)) {
-				button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
-				tempf = (float)data->value - 0.01f * but->a1;
-				if (tempf < softmin) tempf = softmin;
-				data->value = tempf;
-
-				button_activate_state(C, but, BUTTON_STATE_EXIT);
-			}
-			else if (mx > but->rect.xmax - handlewidth) {
-				button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
-
-				tempf = (float)data->value + 0.01f * but->a1;
-				if (tempf > softmax) tempf = softmax;
-				data->value = tempf;
-
-				button_activate_state(C, but, BUTTON_STATE_EXIT);
-			}
-			else {
-				button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
-			}
-		}
-
+		/* start textediting - clicking to increase/decrease numbers is handled via sub-buttons */
+		button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
 		retval = WM_UI_HANDLER_BREAK;
 	}
 	
@@ -4306,6 +4247,40 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 	return retval;
 }
 
+static int ui_do_subbut_NUM(bContext *C, uiBut *but, const uiSubBut *sbut, const wmEvent *event)
+{
+	uiHandleButtonData *data = but->active;
+	const float softmin = but->softmin;
+	const float softmax = but->softmax;
+	const bool is_float = ui_but_is_float(but);
+	const bool increase = (sbut->type == UI_SBUT_TYPE_VAL_INCREASE);
+	float tempf;
+	int temp;
+
+	if (event->type != LEFTMOUSE || event->val != KM_RELEASE || data->dragchange)
+		return WM_UI_HANDLER_CONTINUE;
+
+	button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+	if (is_float) {
+		tempf = (float)data->value + (increase ? 0.01f : -0.01f) * but->a1;
+		CLAMP(tempf, softmin, softmax);
+		data->value = tempf;
+	}
+	else {
+		temp = (int)data->value + (increase ? 1 : -1);
+		if (IN_RANGE_INCL(temp, softmin, softmax))
+			data->value = (double)temp;
+		else
+			data->cancel = true;
+	}
+
+	button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+	/* always break */
+	return WM_UI_HANDLER_BREAK;
+}
+
 static bool ui_numedit_but_SLI(
         uiBut *but, uiHandleButtonData *data,
         int mx, const bool is_horizontal,
@@ -6742,8 +6717,33 @@ static bool ui_but_menu(bContext *C, uiBut *but)
 	return true;
 }
 
+static int ui_do_but_subbut(bContext *C, uiBut *but, uiSubBut *sbut, const wmEvent *event)
+{
+	int retval = WM_UI_HANDLER_CONTINUE;
+
+	BLI_assert(sbut->is_hovered);
+
+	switch (but->type) {
+		case UI_BTYPE_NUM:
+			retval = ui_do_subbut_NUM(C, but, sbut, event);
+			break;
+		default:
+			break;
+	}
+
+	if (retval == WM_UI_HANDLER_BREAK) {
+		BLI_assert(ui_but_contains_point_px(CTX_wm_region(C), but, event->x, event->y));
+		button_activate_exit(C, but, but->active, true, false);
+		/* reactivate highlight state */
+		button_activate_init(C, CTX_wm_region(C), but, BUTTON_ACTIVATE_OVER);
+	}
+
+	return retval;
+}
+
 static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *event)
 {
+	uiSubBut *sbut;
 	uiHandleButtonData *data;
 	int retval;
 
@@ -6887,6 +6887,16 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
 		}
 	}
 
+	sbut = ui_subbut_find_mouse_over(CTX_wm_region(C), but, &event->x);
+
+	if (sbut) {
+		retval = ui_do_but_subbut(C, but, sbut, event);
+
+		if (retval == WM_UI_HANDLER_BREAK) {
+			return retval;
+		}
+	}
+
 	switch (but->type) {
 		case UI_BTYPE_BUT:
 			retval = ui_do_but_BUT(C, but, data, event);
@@ -7356,6 +7366,25 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, const wmEvent *event)
 }
 
 
+static uiSubBut *ui_subbut_find_mouse_over(const ARegion *ar, const uiBut *but, const int mouse_xy[2])
+{
+	uiSubBut *sbut;
+	float mx = mouse_xy[0];
+	float my = mouse_xy[1];
+
+	BLI_assert(ui_but_contains_point_px(ar, but, UNPACK2(mouse_xy)));
+
+	ui_window_to_block_fl(ar, but->block, &mx, &my);
+
+	for (sbut = but->subbuts.first; sbut; sbut = sbut->next) {
+		if (BLI_rcti_isect_x(&sbut->rect, mx)) {
+			return sbut;
+		}
+	}
+	return NULL;
+}
+
+
 static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
 {
 	uiBlock *block;
@@ -8038,6 +8067,31 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu
 
 /************ handle events for an activated button ***********/
 
+static void ui_handle_but_subbuts(ARegion *ar, const uiBut *but, const int mouse_xy[2])
+{
+	uiSubBut *sbut = ui_subbut_find_mouse_over(ar, but, mouse_xy);
+	bool changed = false;
+
+	if (sbut) {
+		if (sbut->is_hovered == false) {
+			sbut->is_hovered = true;
+			changed = true;
+		}
+	}
+	else {
+		for (sbut = but->subbut

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list