Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2014-02-18 04:44:26 +0400
committerCampbell Barton <ideasman42@gmail.com>2014-02-18 04:57:49 +0400
commit5fb2d213905abcb92b79092db6645c5a3a13cd10 (patch)
tree5872feebe22dda66e71e085673a59ea31965c9d6 /source/blender
parent2b0aa105f78c785897a309ed77fb5855082ceafe (diff)
NDOF: support pan/zoom for view2d (nodes, graph editor, sequencer... etc)
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/interface/view2d_ops.c188
1 files changed, 151 insertions, 37 deletions
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index a332e5bbcd7..95859be1ac0 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -126,16 +126,32 @@ static int view_pan_init(bContext *C, wmOperator *op)
return 1;
}
+static int view_pan_poll(bContext *C)
+{
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d;
+
+ /* check if there's a region in context to work with */
+ if (ar == NULL)
+ return 0;
+ v2d = &ar->v2d;
+
+ /* check that 2d-view can pan */
+ if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y))
+ return 0;
+
+ /* view can pan */
+ return 1;
+}
+
/* apply transform to view (i.e. adjust 'cur' rect) */
-static void view_pan_apply(bContext *C, wmOperator *op)
+static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float dy)
{
- v2dViewPanData *vpd = op->customdata;
View2D *v2d = vpd->v2d;
- float dx, dy;
/* calculate amount to move view by */
- dx = vpd->facx * (float)RNA_int_get(op->ptr, "deltax");
- dy = vpd->facy * (float)RNA_int_get(op->ptr, "deltay");
+ dx *= vpd->facx;
+ dy *= vpd->facy;
/* only move view on an axis if change is allowed */
if ((v2d->keepofs & V2D_LOCKOFS_X) == 0) {
@@ -164,6 +180,16 @@ static void view_pan_apply(bContext *C, wmOperator *op)
}
}
+static void view_pan_apply(bContext *C, wmOperator *op)
+{
+ v2dViewPanData *vpd = op->customdata;
+
+ view_pan_apply_ex(C, vpd,
+ RNA_int_get(op->ptr, "deltax"),
+ RNA_int_get(op->ptr, "deltay"));
+
+}
+
/* cleanup temp customdata */
static void view_pan_exit(wmOperator *op)
{
@@ -527,6 +553,25 @@ typedef struct v2dViewZoomData {
float mx_2d, my_2d; /* initial mouse location in v2d coords */
} v2dViewZoomData;
+/**
+ * Clamp by convention rather then locking flags,
+ * for ndof and +/- keys
+ */
+static void view_zoom_axis_lock_defaults(bContext *C, bool r_do_zoom_xy[2])
+{
+ ScrArea *sa = CTX_wm_area(C);
+
+ r_do_zoom_xy[0] = true;
+ r_do_zoom_xy[1] = true;
+
+ /* default not to zoom the sequencer vertically */
+ if (sa && sa->spacetype == SPACE_SEQ) {
+ ARegion *ar = CTX_wm_region(C);
+
+ if (ar && ar->regiontype != RGN_TYPE_PREVIEW)
+ r_do_zoom_xy = false;
+ }
+}
/* initialize panning customdata */
static int view_zoomdrag_init(bContext *C, wmOperator *op)
@@ -575,19 +620,16 @@ static int view_zoom_poll(bContext *C)
}
/* apply transform to view (i.e. adjust 'cur' rect) */
-static void view_zoomstep_apply(bContext *C, wmOperator *op)
+static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool use_mousepos,
+ const float facx, const float facy)
{
- v2dViewZoomData *vzd = op->customdata;
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
- float dx, dy, facx, facy;
-
+ float dx, dy;
+
/* calculate amount to move view by, ensuring symmetry so the
* old zoom level is restored after zooming back the same amount
*/
- facx = RNA_float_get(op->ptr, "zoomfacx");
- facy = RNA_float_get(op->ptr, "zoomfacy");
-
if (facx >= 0.0f) {
dx = BLI_rctf_size_x(&v2d->cur) * facx;
dy = BLI_rctf_size_y(&v2d->cur) * facy;
@@ -609,7 +651,7 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
v2d->cur.xmax -= 2 * dx;
}
else {
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur);
float mval_faci = 1.0f - mval_fac;
float ofs = (mval_fac * dx) - (mval_faci * dx);
@@ -634,7 +676,7 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
v2d->cur.ymax -= 2 * dy;
}
else {
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ if (use_mousepos && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur);
float mval_faci = 1.0f - mval_fac;
float ofs = (mval_fac * dy) - (mval_faci * dy);
@@ -657,6 +699,14 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
}
+static void view_zoomstep_apply(bContext *C, wmOperator *op)
+{
+ v2dViewZoomData *vzd = op->customdata;
+ view_zoomstep_apply_ex(C, vzd, true,
+ RNA_float_get(op->ptr, "zoomfacx"),
+ RNA_float_get(op->ptr, "zoomfacy"));
+}
+
/* --------------- Individual Operators ------------------- */
/* cleanup temp customdata */
@@ -673,25 +723,18 @@ static void view_zoomstep_exit(wmOperator *op)
/* this operator only needs this single callback, where it calls the view_zoom_*() methods */
static int view_zoomin_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- bool do_zoom_x = true;
- bool do_zoom_y = true;
+ bool do_zoom_xy[2];
/* check that there's an active region, as View2D data resides there */
if (!view_zoom_poll(C))
return OPERATOR_PASS_THROUGH;
- /* default not to zoom the sequencer vertically */
- if (sa && sa->spacetype == SPACE_SEQ) {
- ARegion *ar = CTX_wm_region(C);
- if (ar && ar->regiontype != RGN_TYPE_PREVIEW)
- do_zoom_y = false;
- }
+ view_zoom_axis_lock_defaults(C, do_zoom_xy);
/* set RNA-Props - zooming in by uniform factor */
- RNA_float_set(op->ptr, "zoomfacx", do_zoom_x ? 0.0375f : 0.0f);
- RNA_float_set(op->ptr, "zoomfacy", do_zoom_y ? 0.0375f : 0.0f);
+ RNA_float_set(op->ptr, "zoomfacx", do_zoom_xy[0] ? 0.0375f : 0.0f);
+ RNA_float_set(op->ptr, "zoomfacy", do_zoom_xy[1] ? 0.0375f : 0.0f);
/* apply movement, then we're done */
view_zoomstep_apply(C, op);
@@ -742,25 +785,17 @@ static void VIEW2D_OT_zoom_in(wmOperatorType *ot)
/* this operator only needs this single callback, where it calls the view_zoom_*() methods */
static int view_zoomout_exec(bContext *C, wmOperator *op)
{
- ScrArea *sa = CTX_wm_area(C);
- bool do_zoom_x = true;
- bool do_zoom_y = true;
+ bool do_zoom_xy[2];
/* check that there's an active region, as View2D data resides there */
if (!view_zoom_poll(C))
return OPERATOR_PASS_THROUGH;
- /* default not to zoom the sequencer vertically */
- if (sa && sa->spacetype == SPACE_SEQ) {
- ARegion *ar = CTX_wm_region(C);
-
- if (ar && ar->regiontype != RGN_TYPE_PREVIEW)
- do_zoom_y = false;
- }
+ view_zoom_axis_lock_defaults(C, do_zoom_xy);
/* set RNA-Props - zooming in by uniform factor */
- RNA_float_set(op->ptr, "zoomfacx", do_zoom_x ? -0.0375f : 0.0f);
- RNA_float_set(op->ptr, "zoomfacy", do_zoom_y ? -0.0375f : 0.0f);
+ RNA_float_set(op->ptr, "zoomfacx", do_zoom_xy[0] ? -0.0375f : 0.0f);
+ RNA_float_set(op->ptr, "zoomfacy", do_zoom_xy[1] ? -0.0375f : 0.0f);
/* apply movement, then we're done */
view_zoomstep_apply(C, op);
@@ -1220,6 +1255,81 @@ static void VIEW2D_OT_zoom_border(wmOperatorType *ot)
WM_operator_properties_gesture_border(ot, false);
}
+
+static int view2d_ndof_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (event->type != NDOF_MOTION) {
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
+
+ float dt = ndof->dt;
+ /* tune these until it feels right */
+ const float zoom_sensitivity = 0.5f;
+ const float pan_sensitivity = 10.0f; /* match view3d ortho */
+ const bool has_translate = (ndof->tvec[0] && ndof->tvec[1]) && view_pan_poll(C);
+ const bool has_zoom = (ndof->tvec[2] != 0.0f) && view_zoom_poll(C);
+
+ if (has_translate) {
+ if (view_pan_init(C, op)) {
+ v2dViewPanData *vpd;
+ float pan_vec[2];
+
+ pan_vec[0] = ndof->tvec[0] * ((U.ndof_flag & NDOF_PANX_INVERT_AXIS) ? -1.0f : 1.0f);
+ pan_vec[1] = ndof->tvec[1] * ((U.ndof_flag & NDOF_PANY_INVERT_AXIS) ? -1.0f : 1.0f);
+
+ pan_vec[0] *= pan_sensitivity;
+ pan_vec[1] *= pan_sensitivity;
+
+ vpd = op->customdata;
+
+ view_pan_apply_ex(C, vpd, pan_vec[0], pan_vec[1]);
+
+ view_pan_exit(op);
+ }
+ }
+
+ if (has_zoom) {
+ if (view_zoomdrag_init(C, op)) {
+ v2dViewZoomData *vzd;
+ float zoom_factor = zoom_sensitivity * dt * -ndof->tvec[2];
+
+ bool do_zoom_xy[2];
+
+ if (U.ndof_flag & NDOF_ZOOM_INVERT)
+ zoom_factor = -zoom_factor;
+
+ view_zoom_axis_lock_defaults(C, do_zoom_xy);
+
+ vzd = op->customdata;
+
+ view_zoomstep_apply_ex(C, vzd, false,
+ do_zoom_xy[0] ? zoom_factor : 0.0f,
+ do_zoom_xy[1] ? zoom_factor : 0.0f);
+
+ view_zoomstep_exit(op);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+ }
+}
+
+static void VIEW2D_OT_ndof(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "NDOF Pan/Zoom";
+ ot->idname = "VIEW2D_OT_ndof";
+ ot->description = "Use a 3D mouse device to pan/zoom the view";
+
+ /* api callbacks */
+ ot->invoke = view2d_ndof_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_LOCK_BYPASS;
+}
+
/* ********************************************************* */
/* SMOOTH VIEW */
@@ -1898,6 +2008,8 @@ void UI_view2d_operatortypes(void)
WM_operatortype_append(VIEW2D_OT_zoom);
WM_operatortype_append(VIEW2D_OT_zoom_border);
+ WM_operatortype_append(VIEW2D_OT_ndof);
+
WM_operatortype_append(VIEW2D_OT_smoothview);
WM_operatortype_append(VIEW2D_OT_scroller_activate);
@@ -1926,6 +2038,8 @@ void UI_view2d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_ndof", NDOF_MOTION, 0, 0, 0);
+
/* zoom - single step */
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);