[Bf-blender-cvs] [daf4a3b] wiggly-widgets: Widget precision tweaking support

Julian Eisel noreply at git.blender.org
Fri Dec 4 00:49:55 CET 2015


Commit: daf4a3b16635f4f1e489291ca62b7f36662b7f88
Author: Julian Eisel
Date:   Fri Dec 4 00:35:35 2015 +0100
Branches: wiggly-widgets
https://developer.blender.org/rBdaf4a3b16635f4f1e489291ca62b7f36662b7f88

Widget precision tweaking support

Adds support for precision tweaking by holding shift. For now used by arrow-widgets only, rest can be adapted later.

Also - and this shouldn't have any noticeable influence for users, widget tweaking is handled via a modal operator now (WIDGETGROUP_OT_widget_tweak). This way, the shortcut for toggling precision tweaking doesn't have to be hardcoded.

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

M	source/blender/editors/transform/transform_manipulator.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_generic_widgets.c
M	source/blender/windowmanager/intern/wm_operators.c
M	source/blender/windowmanager/intern/wm_widgets.c
M	source/blender/windowmanager/wm.h

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

diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 6644f4a..aff24a1 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -1009,7 +1009,7 @@ static ManipulatorGroup *manipulatorgroup_init(
 /**
  * Custom handler for manipulator widgets
  */
-static int manipulator_handler(bContext *C, const wmEvent *UNUSED(event), wmWidget *widget)
+static int manipulator_handler(bContext *C, const wmEvent *UNUSED(event), wmWidget *widget, const int UNUSED(flag))
 {
 	const ScrArea *sa = CTX_wm_area(C);
 	ARegion *ar = CTX_wm_region(C);
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index f624f2a..9f6f2f9 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -508,7 +508,7 @@ bool        WM_event_is_tablet(const struct wmEvent *event);
 struct wmWidget *WM_widget_new(void (*draw)(const struct bContext *, struct wmWidget *),
                                void (*render_3d_intersection)(const struct bContext *, struct wmWidget *, int),
                                int  (*intersect)(struct bContext *, const struct wmEvent *, struct wmWidget *),
-                               int  (*handler)(struct bContext *, const struct wmEvent *, struct wmWidget *));
+                               int  (*handler)(struct bContext *, const struct wmEvent *, struct wmWidget *, const int));
 
 void  WM_widgetmap_widgets_update(const struct bContext *C, struct wmWidgetMap *wmap);
 void  WM_widgetmap_widgets_draw(const struct bContext *C, const struct wmWidgetMap *wmap,
@@ -534,6 +534,16 @@ enum widgetflags {
 	WM_WIDGET_SELECTABLE  = (1 << 8),
 };
 
+/**
+ * \brief Widget tweak flag.
+ * Bitflag passed to widget while tweaking.
+ */
+enum {
+	/* drag with extra precision (shift)
+	 * NOTE: Widgets are responsible for handling this (widget->handler callback)! */
+	WM_WIDGET_TWEAK_PRECISE = (1 << 0),
+};
+
 void WM_widget_set_property(struct wmWidget *, int slot, struct PointerRNA *ptr, const char *propname);
 struct PointerRNA *WM_widget_set_operator(struct wmWidget *, const char *opname);
 void WM_widget_set_func_select(
diff --git a/source/blender/windowmanager/intern/wm_generic_widgets.c b/source/blender/windowmanager/intern/wm_generic_widgets.c
index a564ff5..9434968 100644
--- a/source/blender/windowmanager/intern/wm_generic_widgets.c
+++ b/source/blender/windowmanager/intern/wm_generic_widgets.c
@@ -196,10 +196,16 @@ typedef struct ArrowInteraction {
 	float orig_offset;
 	float orig_scale;
 
-	/* direction vector, projected in screen space */
-	float proj_direction[2];
+	/* offset of last handling step */
+	float prev_offset;
+	/* Total offset added by precision tweaking.
+	 * Needed to allow toggling precision on/off without causing jumps */
+	float precision_offset;
 } ArrowInteraction;
 
+/* factor for precision tweaking */
+#define ARROW_PRECISION_FAC 0.05f
+
 
 static void widget_arrow_get_final_pos(wmWidget *widget, float r_pos[3])
 {
@@ -376,12 +382,13 @@ static void widget_arrow_draw(const bContext *UNUSED(C), wmWidget *widget)
  */
 #define USE_ABS_HANDLE_RANGE
 
-static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *widget)
+static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *widget, const int flag)
 {
 	ArrowWidget *arrow = (ArrowWidget *)widget;
 	ArrowInteraction *data = widget->interaction_data;
 	ARegion *ar = CTX_wm_region(C);
 	RegionView3D *rv3d = ar->regiondata;
+	const bool use_precision = (flag & WM_WIDGET_TWEAK_PRECISE);
 
 	float orig_origin[4];
 	float viewvec[3], tangent[3], plane[3];
@@ -461,12 +468,22 @@ static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *wid
 		facdir = (m_diff[1] < 0.0) ? -1.0 : 1.0;
 	}
 
+
+	const float ofs_new = facdir * len_v3(offset);
+
 	/* set the property for the operator and call its modal function */
 	if (widget->props[ARROW_SLOT_OFFSET_WORLD_SPACE]) {
 		float max = arrow->min + arrow->range;
 		float value;
 
-		value = data->orig_offset + facdir * len_v3(offset);
+		if (use_precision) {
+			/* add delta offset of this step to total precision_offset */
+			data->precision_offset += ofs_new - data->prev_offset;
+		}
+		data->prev_offset = ofs_new;
+
+		value = data->orig_offset + ofs_new - data->precision_offset * (1.0f - ARROW_PRECISION_FAC);
+
 		if (arrow->style & WIDGET_ARROW_STYLE_CONSTRAINED) {
 			if (arrow->style & WIDGET_ARROW_STYLE_INVERTED)
 				value = max - (value * arrow->range / arrow->range_fac);
@@ -483,6 +500,7 @@ static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *wid
 			CLAMP(value, arrow->min, max);
 		}
 
+
 		PointerRNA ptr = widget->ptr[ARROW_SLOT_OFFSET_WORLD_SPACE];
 		PropertyRNA *prop = widget->props[ARROW_SLOT_OFFSET_WORLD_SPACE];
 
@@ -506,11 +524,12 @@ static int widget_arrow_handler(bContext *C, const wmEvent *event, wmWidget *wid
 			arrow->offset = value;
 	}
 	else {
-		arrow->offset = facdir * len_v3(offset);
+		arrow->offset = ofs_new;
 	}
 
 	/* tag the region for redraw */
 	ED_region_tag_redraw(ar);
+	WM_event_add_mousemove(C);
 
 	return OPERATOR_PASS_THROUGH;
 }
@@ -1369,7 +1388,7 @@ static int widget_rect_transform_invoke(bContext *UNUSED(C), const wmEvent *even
 	return OPERATOR_RUNNING_MODAL;
 }
 
-static int widget_rect_transform_handler(bContext *C, const wmEvent *event, wmWidget *widget)
+static int widget_rect_transform_handler(bContext *C, const wmEvent *event, wmWidget *widget, const int UNUSED(flag))
 {
 	RectTransformWidget *cage = (RectTransformWidget *)widget;
 	RectTransformInteraction *data = widget->interaction_data;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 006b570..f5c891c 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -5330,10 +5330,8 @@ void wm_operatortype_init(void)
 	WM_operatortype_append(WM_OT_doc_view_manual_ui_context);
 
 	/* widgets */
-	WM_operatortype_append(WIDGETGROUP_OT_widget_set_active);
 	WM_operatortype_append(WIDGETGROUP_OT_widget_select);
 	WM_operatortype_append(WIDGETGROUP_OT_widget_tweak);
-	WM_operatortype_append(WIDGETGROUP_OT_widget_tweak_cancel);
 }
 
 /* circleselect-like modal operators */
diff --git a/source/blender/windowmanager/intern/wm_widgets.c b/source/blender/windowmanager/intern/wm_widgets.c
index 03915f6..0b53725 100644
--- a/source/blender/windowmanager/intern/wm_widgets.c
+++ b/source/blender/windowmanager/intern/wm_widgets.c
@@ -200,7 +200,7 @@ static GHash *wm_widgetmap_widget_hash_new(
 wmWidget *WM_widget_new(void (*draw)(const bContext *C, wmWidget *customdata),
                         void (*render_3d_intersection)(const bContext *C, wmWidget *customdata, int selectionbase),
                         int  (*intersect)(bContext *C, const wmEvent *event, wmWidget *widget),
-                        int  (*handler)(bContext *C, const wmEvent *event, wmWidget *widget))
+                        int  (*handler)(bContext *C, const wmEvent *event, wmWidget *widget, const int flag))
 {
 	wmWidget *widget = MEM_callocN(sizeof(wmWidget), "widget");
 
@@ -658,49 +658,6 @@ void WM_widget_set_colors(wmWidget *widget, const float col[4], const float col_
  *
  * \{ */
 
-static int widget_set_active_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
-	ARegion *ar = CTX_wm_region(C);
-	const bool deactivate = RNA_boolean_get(op->ptr, "deactivate");
-
-	for (wmWidgetMap *wmap = ar->widgetmaps.first; wmap; wmap = wmap->next) {
-		if (deactivate) {
-			wm_widgetmap_set_active_widget(wmap, C, event, NULL);
-
-			/* ugly hack - send widget release event */
-			((wmEvent *)event)->type = EVT_WIDGET_RELEASED;
-		}
-		else {
-			wmWidget *widget = wmap->wmap_context.highlighted_widget;
-			if (widget) {
-				wm_widgetmap_set_active_widget(wmap, C, event, widget);
-				break;
-			}
-			else {
-				BLI_assert(0);
-				return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
-			}
-		}
-	}
-
-	return OPERATOR_FINISHED;
-}
-
-void WIDGETGROUP_OT_widget_set_active(wmOperatorType *ot)
-{
-	/* identifiers */
-	ot->name = "Widget Activate";
-	ot->description = "Activate the currently highlighted widget";
-	ot->idname = "WIDGETGROUP_OT_widget_set_active";
-
-	/* api callbacks */
-	ot->invoke = widget_set_active_invoke;
-
-	ot->flag = OPTYPE_UNDO;
-
-	RNA_def_boolean(ot->srna, "deactivate", 0, "Deactivate", "Deactivate currently active widget");
-}
-
 /**
  * Deselect all selected widgets in \a wmap.
  * \return if selection has changed.
@@ -917,86 +874,143 @@ void WIDGETGROUP_OT_widget_select(wmOperatorType *ot)
 	WM_operator_properties_mouse_select(ot);
 }
 
-/**
- * Search for an active widget in region \a ar.
- */
-static wmWidget *widget_find_active_in_region(const ARegion *ar, wmWidgetMap **r_wmap)
+typedef struct WidgetTweakData {
+	wmWidgetMap *wmap;
+	wmWidget *active;
+
+	int init_event; /* initial event type */
+	int flag;       /* tweak flags */
+} WidgetTweakData;
+
+enum {
+	TWEAK_MODAL_CANCEL = 1,
+	TWEAK_MODAL_CONFIRM,
+	TWEAK_MODAL_PRECISION_ON,
+	TWEAK_MODAL_PRECISION_OFF,
+};
+
+static void widget_tweak_finish(bContext *C, wmOperator *op)
 {
-	for (*r_wmap = ar->widgetmaps.first; *r_wmap; *r_wmap = (*r_wmap)->next) {
-		if ((*r_wmap)->wmap_context.active_widget) {
-			return (*r_wmap)->wmap_context.active_widget;
-		}
-	}
+	WidgetTweakData *wtweak = op->customdata;
+	wm_widgetmap_set_active_widget(wtweak->wmap, C, NULL, NULL);
+	MEM_freeN(wtweak);
+}
 
-	*r_wmap = NULL;
-	return NULL;
+static void widget_tweak_cancel(bContext *C, wmOperator *op)
+{
+	WidgetTweakData *wtweak = op->customdata;
+	if (wtweak->active->cancel) {
+		wtweak->active->cancel(C, wtweak->active);
+	}
+	widget_tweak_finish(C, op);
 }
 
-static int widget_tweak_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int widget_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
 {
-	ARegion *ar = CTX_wm_region(C);
-	wmWidgetMap *wmap;
-	wmWidget *widget = widget_find_active_in_region(ar, &wmap);
+	WidgetTweakData *wtw

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list