[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