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:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/object/object_bake.c4
-rw-r--r--source/blender/editors/space_image/image_intern.h1
-rw-r--r--source/blender/editors/space_image/image_ops.c54
-rw-r--r--source/blender/editors/space_image/space_image.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c549
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c199
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h4
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c11
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h19
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c23
-rw-r--r--source/blender/windowmanager/WM_types.h20
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c54
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c112
-rw-r--r--source/blender/windowmanager/intern/wm_window.c4
-rw-r--r--source/blender/windowmanager/wm_event_types.h50
15 files changed, 690 insertions, 418 deletions
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index bdd911d68ee..679e4e58017 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -860,6 +860,10 @@ static void finish_images(MultiresBakeRender *bkr)
RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter);
ibuf->userflags|= IB_BITMAPDIRTY;
+
+ if(ibuf->rect_float)
+ ibuf->userflags|= IB_RECT_INVALID;
+
if(ibuf->mipmap[0]) {
ibuf->userflags|= IB_MIPMAP_INVALID;
imb_freemipmapImBuf(ibuf);
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index e9e77ddf430..399157da85c 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -73,6 +73,7 @@ void IMAGE_OT_view_zoom(struct wmOperatorType *ot);
void IMAGE_OT_view_zoom_in(struct wmOperatorType *ot);
void IMAGE_OT_view_zoom_out(struct wmOperatorType *ot);
void IMAGE_OT_view_zoom_ratio(struct wmOperatorType *ot);
+void IMAGE_OT_view_ndof(struct wmOperatorType *ot);
void IMAGE_OT_new(struct wmOperatorType *ot);
void IMAGE_OT_open(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 10b8cb238aa..77fb129e278 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -437,6 +437,60 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
"Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out.", -FLT_MAX, FLT_MAX);
}
+/********************** NDOF operator *********************/
+
+/* Combined pan/zoom from a 3D mouse device.
+ * Z zooms, XY pans
+ * "view" (not "paper") control -- user moves the viewpoint, not the image being viewed
+ * that explains the negative signs in the code below
+ */
+
+static int view_ndof_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ SpaceImage *sima= CTX_wm_space_image(C);
+ ARegion *ar= CTX_wm_region(C);
+
+ wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata;
+
+ float dt = ndof->dt > 0.25f ? 0.0125f : ndof->dt;
+ /* this is probably the first event for this motion, so set dt to something reasonable
+ * TODO: replace such guesswork with a flag or field from the NDOF manager
+ */
+
+ /* tune these until it feels right */
+ const float zoom_sensitivity = 0.5f;
+ const float pan_sensitivity = 300.f;
+
+ float pan_x = pan_sensitivity * dt * ndof->tx / sima->zoom;
+ float pan_y = pan_sensitivity * dt * ndof->ty / sima->zoom;
+
+ /* "mouse zoom" factor = 1 + (dx + dy) / 300
+ * what about "ndof zoom" factor? should behave like this:
+ * at rest -> factor = 1
+ * move forward -> factor > 1
+ * move backward -> factor < 1
+ */
+ float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tz;
+
+ sima_zoom_set_factor(sima, ar, zoom_factor);
+ sima->xof += pan_x;
+ sima->yof += pan_y;
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_view_ndof(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "NDOF Pan/Zoom";
+ ot->idname= "IMAGE_OT_view_ndof";
+
+ /* api callbacks */
+ ot->invoke= view_ndof_invoke;
+}
+
/********************** view all operator *********************/
/* Updates the fields of the View2D member of the SpaceImage struct.
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 2e9544f5d20..afab4ede229 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -469,6 +469,7 @@ static void image_operatortypes(void)
WM_operatortype_append(IMAGE_OT_view_zoom_in);
WM_operatortype_append(IMAGE_OT_view_zoom_out);
WM_operatortype_append(IMAGE_OT_view_zoom_ratio);
+ WM_operatortype_append(IMAGE_OT_view_ndof);
WM_operatortype_append(IMAGE_OT_new);
WM_operatortype_append(IMAGE_OT_open);
@@ -518,6 +519,9 @@ static void image_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MOUSEPAN, 0, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); // or view selected?
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_ndof", NDOF_MOTION, 0, 0, 0);
+
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 9ff73767b4c..0c07df9fd01 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -929,6 +929,163 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
}
+// NDOF utility functions
+// (should these functions live in this file?)
+float ndof_to_angle_axis(struct wmNDOFMotionData* ndof, float axis[3])
+ {
+ const float x = ndof->rx;
+ const float y = ndof->ry;
+ const float z = ndof->rz;
+
+ float angular_velocity = sqrtf(x*x + y*y + z*z);
+ float angle = ndof->dt * angular_velocity;
+
+ float scale = 1.f / angular_velocity;
+
+ // normalize
+ axis[0] = scale * x;
+ axis[1] = scale * y;
+ axis[2] = scale * z;
+
+ return angle;
+ }
+
+void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4])
+ {
+ const float x = ndof->rx;
+ const float y = ndof->ry;
+ const float z = ndof->rz;
+
+ float angular_velocity = sqrtf(x*x + y*y + z*z);
+ float angle = ndof->dt * angular_velocity;
+
+ // combined scaling factor -- normalize axis while converting to quaternion
+ float scale = sin(0.5f * angle) / angular_velocity;
+
+ // convert axis-angle to quaternion
+ q[0] = cos(0.5f * angle);
+ q[1] = scale * x;
+ q[2] = scale * y;
+ q[3] = scale * z;
+ }
+
+static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
+// -- "orbit" navigation (trackball/turntable)
+// -- zooming
+// -- panning in rotationally-locked views
+{
+ RegionView3D* rv3d = CTX_wm_region_view3d(C);
+ wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata;
+
+ const float dt = ndof->dt;
+
+ // tune these until everything feels right
+ const float rot_sensitivity = 1.f;
+ const float zoom_sensitivity = 1.f;
+ const float pan_sensitivity = 1.f;
+
+ // rather have bool, but...
+ int has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz);
+
+ //#define DEBUG_NDOF_MOTION
+ #ifdef DEBUG_NDOF_MOTION
+ printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n",
+ ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt);
+ #endif
+
+ if (ndof->tz) {
+ // Zoom!
+ // velocity should be proportional to the linear velocity attained by rotational motion of same strength
+ // [got that?]
+ // proportional to arclength = radius * angle
+
+ float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz;
+ rv3d->dist += zoom_distance;
+ }
+
+ if (rv3d->viewlock == RV3D_LOCKED) {
+ /* rotation not allowed -- explore panning options instead */
+ float view_inv[4];
+ float pan_vec[3] = {ndof->tx, ndof->ty, 0};
+ mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
+
+ /* transform motion from view to world coordinates */
+ invert_qt_qt(view_inv, rv3d->viewquat);
+ mul_qt_v3(view_inv, pan_vec);
+
+ /* move center of view opposite of hand motion (this is camera mode, not object mode) */
+ sub_v3_v3(rv3d->ofs, pan_vec);
+ }
+
+ if (has_rotation) {
+
+ rv3d->view = RV3D_VIEW_USER;
+
+ if (U.flag & USER_TRACKBALL) {
+
+ float rot[4];
+ float view_inv[4], view_inv_conj[4];
+
+ ndof_to_quat(ndof, rot);
+ // scale by rot_sensitivity?
+ // mul_qt_fl(rot, rot_sensitivity);
+
+ invert_qt_qt(view_inv, rv3d->viewquat);
+ copy_qt_qt(view_inv_conj, view_inv);
+ conjugate_qt(view_inv_conj);
+
+ // transform rotation from view to world coordinates
+ mul_qt_qtqt(rot, view_inv, rot);
+ mul_qt_qtqt(rot, rot, view_inv_conj);
+
+ // apply rotation
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+
+ } else {
+ /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
+ float angle, rot[4];
+ float xvec[3] = {1,0,0};
+
+ /* Determine the direction of the x vector (for rotating up and down) */
+ float view_inv[4];
+ invert_qt_qt(view_inv, rv3d->viewquat);
+ mul_qt_v3(view_inv, xvec);
+
+ /* Perform the up/down rotation */
+ angle = rot_sensitivity * dt * ndof->rx;
+ rot[0] = cos(angle);
+ mul_v3_v3fl(rot+1, xvec, sin(angle));
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+
+ /* Perform the orbital rotation */
+ angle = rot_sensitivity * dt * ndof->ry;
+ rot[0] = cos(angle);
+ rot[1] = rot[2] = 0.0;
+ rot[3] = sin(angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+ }
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void VIEW3D_OT_ndof(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Navigate view";
+ ot->description = "Navigate the view using a 3D mouse.";
+ ot->idname = "VIEW3D_OT_ndof";
+
+ /* api callbacks */
+ ot->invoke = ndof_orbit_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
+
/* ************************ viewmove ******************************** */
@@ -3196,398 +3353,6 @@ int ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], cons
return (*depth==FLT_MAX) ? 0:1;
}
-/* ********************* NDOF ************************ */
-/* note: this code is confusing and unclear... (ton) */
-/* **************************************************** */
-
-// ndof scaling will be moved to user setting.
-// In the mean time this is just a place holder.
-
-// Note: scaling in the plugin and ghostwinlay.c
-// should be removed. With driver default setting,
-// each axis returns approx. +-200 max deflection.
-
-// The values I selected are based on the older
-// polling i/f. With event i/f, the sensistivity
-// can be increased for improved response from
-// small deflections of the device input.
-
-
-// lukep notes : i disagree on the range.
-// the normal 3Dconnection driver give +/-400
-// on defaut range in other applications
-// and up to +/- 1000 if set to maximum
-// because i remove the scaling by delta,
-// which was a bad idea as it depend of the system
-// speed and os, i changed the scaling values, but
-// those are still not ok
-
-#if 0
-static float ndof_axis_scale[6] = {
- +0.01, // Tx
- +0.01, // Tz
- +0.01, // Ty
- +0.0015, // Rx
- +0.0015, // Rz
- +0.0015 // Ry
-};
-
-static void filterNDOFvalues(float *sbval)
-{
- int i=0;
- float max = 0.0;
-
- for (i =0; i<6;i++)
- if (fabs(sbval[i]) > max)
- max = fabs(sbval[i]);
- for (i =0; i<6;i++)
- if (fabs(sbval[i]) != max )
- sbval[i]=0.0;
-}
-
-// statics for controlling rv3d->dist corrections.
-// viewmoveNDOF zeros and adjusts rv3d->ofs.
-// viewmove restores based on dz_flag state.
-
-int dz_flag = 0;
-float m_dist;
-
-void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int UNUSED(mode))
-{
- RegionView3D *rv3d= ar->regiondata;
- int i;
- float phi;
- float dval[7];
- // static fval[6] for low pass filter; device input vector is dval[6]
- static float fval[6];
- float tvec[3],rvec[3];
- float q1[4];
- float mat[3][3];
- float upvec[3];
-
-
- /*----------------------------------------------------
- * sometimes this routine is called from headerbuttons
- * viewmove needs to refresh the screen
- */
-// XXX areawinset(ar->win);
-
-
- // fetch the current state of the ndof device
-// XXX getndof(dval);
-
- if (v3d->ndoffilter)
- filterNDOFvalues(fval);
-
- // Scale input values
-
-// if(dval[6] == 0) return; // guard against divide by zero
-
- for(i=0;i<6;i++) {
-
- // user scaling
- dval[i] = dval[i] * ndof_axis_scale[i];
- }
-
-
- // low pass filter with zero crossing reset
-
- for(i=0;i<6;i++) {
- if((dval[i] * fval[i]) >= 0)
- dval[i] = (fval[i] * 15 + dval[i]) / 16;
- else
- fval[i] = 0;
- }
-
-
- // force perspective mode. This is a hack and is
- // incomplete. It doesn't actually effect the view
- // until the first draw and doesn't update the menu
- // to reflect persp mode.
-
- rv3d->persp = RV3D_PERSP;
-
-
- // Correct the distance jump if rv3d->dist != 0
-
- // This is due to a side effect of the original
- // mouse view rotation code. The rotation point is
- // set a distance in front of the viewport to
- // make rotating with the mouse look better.
- // The distance effect is written at a low level
- // in the view management instead of the mouse
- // view function. This means that all other view
- // movement devices must subtract this from their
- // view transformations.
-
- if(rv3d->dist != 0.0) {
- dz_flag = 1;
- m_dist = rv3d->dist;
- upvec[0] = upvec[1] = 0;
- upvec[2] = rv3d->dist;
- copy_m3_m4(mat, rv3d->viewinv);
- mul_m3_v3(mat, upvec);
- sub_v3_v3(rv3d->ofs, upvec);
- rv3d->dist = 0.0;
- }
-
-
- // Apply rotation
- // Rotations feel relatively faster than translations only in fly mode, so
- // we have no choice but to fix that here (not in the plugins)
- rvec[0] = -0.5 * dval[3];
- rvec[1] = -0.5 * dval[4];
- rvec[2] = -0.5 * dval[5];
-
- // rotate device x and y by view z
-
- copy_m3_m4(mat, rv3d->viewinv);
- mat[2][2] = 0.0f;
- mul_m3_v3(mat, rvec);
-
- // rotate the view
-
- phi = normalize_v3(rvec);
- if(phi != 0) {
- axis_angle_to_quat(q1,rvec,phi);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
- }
-
-
- // Apply translation
-
- tvec[0] = dval[0];
- tvec[1] = dval[1];
- tvec[2] = -dval[2];
-
- // the next three lines rotate the x and y translation coordinates
- // by the current z axis angle
-
- copy_m3_m4(mat, rv3d->viewinv);
- mat[2][2] = 0.0f;
- mul_m3_v3(mat, tvec);
-
- // translate the view
-
- sub_v3_v3(rv3d->ofs, tvec);
-
-
- /*----------------------------------------------------
- * refresh the screen XXX
- */
-
- // update render preview window
-
-// XXX BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT);
-}
-
-void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int UNUSED(mode))
-{
- RegionView3D *rv3d= ar->regiondata;
- float fval[7];
- float dvec[3];
- float sbadjust = 1.0f;
- float len;
- short use_sel = 0;
- Object *ob = OBACT;
- float m[3][3];
- float m_inv[3][3];
- float xvec[3] = {1,0,0};
- float yvec[3] = {0,-1,0};
- float zvec[3] = {0,0,1};
- float phi;
- float q1[4];
- float obofs[3];
- float reverse;
- //float diff[4];
- float d, curareaX, curareaY;
- float mat[3][3];
- float upvec[3];
-
- /* Sensitivity will control how fast the view rotates. The value was
- * obtained experimentally by tweaking until the author didn't get dizzy watching.
- * Perhaps this should be a configurable user parameter.
- */
- float psens = 0.005f * (float) U.ndof_pan; /* pan sensitivity */
- float rsens = 0.005f * (float) U.ndof_rotate; /* rotate sensitivity */
- float zsens = 0.3f; /* zoom sensitivity */
-
- const float minZoom = -30.0f;
- const float maxZoom = 300.0f;
-
- //reset view type
- rv3d->view = 0;
-//printf("passing here \n");
-//
- if (scene->obedit==NULL && ob && !(ob->mode & OB_MODE_POSE)) {
- use_sel = 1;
- }
-
- if((dz_flag)||rv3d->dist==0) {
- dz_flag = 0;
- rv3d->dist = m_dist;
- upvec[0] = upvec[1] = 0;
- upvec[2] = rv3d->dist;
- copy_m3_m4(mat, rv3d->viewinv);
- mul_m3_v3(mat, upvec);
- add_v3_v3(rv3d->ofs, upvec);
- }
-
- /*----------------------------------------------------
- * sometimes this routine is called from headerbuttons
- * viewmove needs to refresh the screen
- */
-// XXX areawinset(curarea->win);
-
- /*----------------------------------------------------
- * record how much time has passed. clamp at 10 Hz
- * pretend the previous frame occurred at the clamped time
- */
-// now = PIL_check_seconds_timer();
- // frametime = (now - prevTime);
- // if (frametime > 0.1f){ /* if more than 1/10s */
- // frametime = 1.0f/60.0; /* clamp at 1/60s so no jumps when starting to move */
-// }
-// prevTime = now;
- // sbadjust *= 60 * frametime; /* normalize ndof device adjustments to 100Hz for framerate independence */
-
- /* fetch the current state of the ndof device & enforce dominant mode if selected */
-// XXX getndof(fval);
- if (v3d->ndoffilter)
- filterNDOFvalues(fval);
-
-
- // put scaling back here, was previously in ghostwinlay
- fval[0] = fval[0] * (1.0f/600.0f);
- fval[1] = fval[1] * (1.0f/600.0f);
- fval[2] = fval[2] * (1.0f/1100.0f);
- fval[3] = fval[3] * 0.00005f;
- fval[4] =-fval[4] * 0.00005f;
- fval[5] = fval[5] * 0.00005f;
- fval[6] = fval[6] / 1000000.0f;
-
- // scale more if not in perspective mode
- if (rv3d->persp == RV3D_ORTHO) {
- fval[0] = fval[0] * 0.05f;
- fval[1] = fval[1] * 0.05f;
- fval[2] = fval[2] * 0.05f;
- fval[3] = fval[3] * 0.9f;
- fval[4] = fval[4] * 0.9f;
- fval[5] = fval[5] * 0.9f;
- zsens *= 8;
- }
-
- /* set object offset */
- if (ob) {
- obofs[0] = -ob->obmat[3][0];
- obofs[1] = -ob->obmat[3][1];
- obofs[2] = -ob->obmat[3][2];
- }
- else {
- copy_v3_v3(obofs, rv3d->ofs);
- }
-
- /* calc an adjustment based on distance from camera
- disabled per patch 14402 */
- d = 1.0f;
-
-/* if (ob) {
- sub_v3_v3v3(diff, obofs, rv3d->ofs);
- d = len_v3(diff);
- }
-*/
-
- reverse = (rv3d->persmat[2][1] < 0.0f) ? -1.0f : 1.0f;
-
- /*----------------------------------------------------
- * ndof device pan
- */
- psens *= 1.0f + d;
- curareaX = sbadjust * psens * fval[0];
- curareaY = sbadjust * psens * fval[1];
- dvec[0] = curareaX * rv3d->persinv[0][0] + curareaY * rv3d->persinv[1][0];
- dvec[1] = curareaX * rv3d->persinv[0][1] + curareaY * rv3d->persinv[1][1];
- dvec[2] = curareaX * rv3d->persinv[0][2] + curareaY * rv3d->persinv[1][2];
- add_v3_v3(rv3d->ofs, dvec);
-
- /*----------------------------------------------------
- * ndof device dolly
- */
- len = zsens * sbadjust * fval[2];
-
- if (rv3d->persp==RV3D_CAMOB) {
- if(rv3d->persp==RV3D_CAMOB) { /* This is stupid, please fix - TODO */
- rv3d->camzoom+= 10.0f * -len;
- }
- if (rv3d->camzoom < minZoom) rv3d->camzoom = minZoom;
- else if (rv3d->camzoom > maxZoom) rv3d->camzoom = maxZoom;
- }
- else if ((rv3d->dist> 0.001*v3d->grid) && (rv3d->dist<10.0*v3d->far)) {
- rv3d->dist*=(1.0 + len);
- }
-
-
- /*----------------------------------------------------
- * ndof device turntable
- * derived from the turntable code in viewmove
- */
-
- /* Get the 3x3 matrix and its inverse from the quaternion */
- quat_to_mat3( m,rv3d->viewquat);
- invert_m3_m3(m_inv,m);
-
- /* Determine the direction of the x vector (for rotating up and down) */
- /* This can likely be compuated directly from the quaternion. */
- mul_m3_v3(m_inv,xvec);
- mul_m3_v3(m_inv,yvec);
- mul_m3_v3(m_inv,zvec);
-
- /* Perform the up/down rotation */
- phi = sbadjust * rsens * /*0.5f * */ fval[3]; /* spin vertically half as fast as horizontally */
- q1[0] = cos(phi);
- mul_v3_v3fl(q1+1, xvec, sin(phi));
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
-
- if (use_sel) {
- conjugate_qt(q1); /* conj == inv for unit quat */
- sub_v3_v3(rv3d->ofs, obofs);
- mul_qt_v3(q1, rv3d->ofs);
- add_v3_v3(rv3d->ofs, obofs);
- }
-
- /* Perform the orbital rotation */
- /* Perform the orbital rotation
- If the seen Up axis is parallel to the zoom axis, rotation should be
- achieved with a pure Roll motion (no Spin) on the device. When you start
- to tilt, moving from Top to Side view, Spinning will increasingly become
- more relevant while the Roll component will decrease. When a full
- Side view is reached, rotations around the world's Up axis are achieved
- with a pure Spin-only motion. In other words the control of the spinning
- around the world's Up axis should move from the device's Spin axis to the
- device's Roll axis depending on the orientation of the world's Up axis
- relative to the screen. */
- //phi = sbadjust * rsens * reverse * fval[4]; /* spin the knob, y axis */
- phi = sbadjust * rsens * (yvec[2] * fval[4] + zvec[2] * fval[5]);
- q1[0] = cos(phi);
- q1[1] = q1[2] = 0.0;
- q1[3] = sin(phi);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
-
- if (use_sel) {
- conjugate_qt(q1);
- sub_v3_v3(rv3d->ofs, obofs);
- mul_qt_v3(q1, rv3d->ofs);
- add_v3_v3(rv3d->ofs, obofs);
- }
-
- /*----------------------------------------------------
- * refresh the screen
- */
-// XXX scrarea_do_windraw(curarea);
-}
-#endif // if 0, unused NDof code
-
-
/* Gets the view trasnformation from a camera
* currently dosnt take camzoom into account
*
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index ed1ed5b3881..6955aefcb9e 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -29,6 +29,8 @@
/* defines VIEW3D_OT_fly modal operator */
+// #define NDOF_FLY_DEBUG
+
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -158,7 +160,9 @@ typedef struct FlyInfo {
short state;
short use_precision;
short redraw;
- int mval[2];
+
+ int mval[2]; /* latest 2D mouse values */
+ wmNDOFMotionData* ndof; /* latest 3D mouse values */
/* fly state state */
float speed; /* the speed the view is moving per redraw */
@@ -257,6 +261,10 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
fly->ar = CTX_wm_region(C);
fly->scene= CTX_data_scene(C);
+ #ifdef NDOF_FLY_DEBUG
+ puts("\n-- fly begin --");
+ #endif
+
if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) {
BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
return FALSE;
@@ -282,12 +290,14 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
fly->zlock_momentum=0.0f;
fly->grid= 1.0f;
fly->use_precision= 0;
+ fly->redraw= 1;
fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f;
fly->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
VECCOPY2D(fly->mval, event->mval)
+ fly->ndof = NULL;
fly->time_lastdraw= fly->time_lastwheel= PIL_check_seconds_timer();
@@ -329,8 +339,17 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
/* perspective or ortho */
if (fly->rv3d->persp==RV3D_ORTHO)
fly->rv3d->persp= RV3D_PERSP; /*if ortho projection, make perspective */
+
copy_qt_qt(fly->rot_backup, fly->rv3d->viewquat);
copy_v3_v3(fly->ofs_backup, fly->rv3d->ofs);
+
+ /* the dist defines a vector that is infront of the offset
+ to rotate the view about.
+ this is no good for fly mode because we
+ want to rotate about the viewers center.
+ but to correct the dist removal we must
+ alter offset so the view doesn't jump. */
+
fly->rv3d->dist= 0.0f;
upvec[2]= fly->dist_backup; /*x and y are 0*/
@@ -338,7 +357,6 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even
sub_v3_v3(fly->rv3d->ofs, upvec);
/*Done with correcting for the dist*/
}
-
/* center the mouse, probably the UI mafia are against this but without its quite annoying */
WM_cursor_warp(CTX_wm_window(C), fly->ar->winrct.xmin + fly->ar->winx/2, fly->ar->winrct.ymin + fly->ar->winy/2);
@@ -356,6 +374,10 @@ static int flyEnd(bContext *C, FlyInfo *fly)
if(fly->state == FLY_RUNNING)
return OPERATOR_RUNNING_MODAL;
+ #ifdef NDOF_FLY_DEBUG
+ puts("\n-- fly end --");
+ #endif
+
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer);
ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel);
@@ -401,6 +423,9 @@ static int flyEnd(bContext *C, FlyInfo *fly)
if(fly->obtfm)
MEM_freeN(fly->obtfm);
+ if(fly->ndof)
+ MEM_freeN(fly->ndof);
+
if(fly->state == FLY_CONFIRM) {
MEM_freeN(fly);
return OPERATOR_FINISHED;
@@ -412,12 +437,54 @@ static int flyEnd(bContext *C, FlyInfo *fly)
static void flyEvent(FlyInfo *fly, wmEvent *event)
{
- if (event->type == TIMER && event->customdata == fly->timer) {
- fly->redraw = 1;
- }
- else if (event->type == MOUSEMOVE) {
+ if (event->type == MOUSEMOVE) {
VECCOPY2D(fly->mval, event->mval);
- } /* handle modal keymap first */
+ }
+ else if (event->type == NDOF_MOTION) {
+ // do these automagically get delivered? yes.
+ // puts("ndof motion detected in fly mode!");
+ // static const char* tag_name = "3D mouse position";
+
+ wmNDOFMotionData* incoming_ndof = (wmNDOFMotionData*) event->customdata;
+ switch (incoming_ndof->progress)
+ {
+ case P_STARTING:
+ // start keeping track of 3D mouse position
+ #ifdef NDOF_FLY_DEBUG
+ puts("start keeping track of 3D mouse position");
+ #endif
+ // fall through...
+ case P_IN_PROGRESS:
+ // update 3D mouse position
+ #ifdef NDOF_FLY_DEBUG
+ putchar('.'); fflush(stdout);
+ #endif
+ if (fly->ndof == NULL)
+ // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
+ fly->ndof = MEM_dupallocN(incoming_ndof);
+ // fly->ndof = malloc(sizeof(wmNDOFMotionData));
+ else
+ memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
+ break;
+ case P_FINISHING:
+ // stop keeping track of 3D mouse position
+ #ifdef NDOF_FLY_DEBUG
+ puts("stop keeping track of 3D mouse position");
+ #endif
+ if (fly->ndof)
+ {
+ MEM_freeN(fly->ndof);
+ // free(fly->ndof);
+ fly->ndof = NULL;
+ }
+ /* update the time else the view will jump when 2D mouse/timer resume */
+ fly->time_lastdraw= PIL_check_seconds_timer();
+ break;
+ default:
+ ; // should always be one of the above 3
+ }
+ }
+ /* handle modal keymap first */
else if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
case FLY_MODAL_CANCEL:
@@ -528,7 +595,6 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
case FLY_MODAL_PRECISION_DISABLE:
fly->use_precision= FALSE;
break;
-
}
}
}
@@ -567,16 +633,14 @@ static int flyApply(bContext *C, FlyInfo *fly)
unsigned char
apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/
+ #ifdef NDOF_FLY_DEBUG
+ static unsigned int iteration = 1;
+ printf("fly timer %d\n", iteration++);
+ #endif
+
if(fly->root_parent)
ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist);
- /* the dist defines a vector that is infront of the offset
- to rotate the view about.
- this is no good for fly mode because we
- want to rotate about the viewers center.
- but to correct the dist removal we must
- alter offset so the view doesn't jump. */
-
xmargin= ar->winx/20.0f;
ymargin= ar->winy/20.0f;
@@ -622,6 +686,8 @@ static int flyApply(bContext *C, FlyInfo *fly)
float time_redraw;
float time_redraw_clamped;
+ fly->redraw= 1;
+
time_current= PIL_check_seconds_timer();
time_redraw= (float)(time_current - fly->time_lastdraw);
time_redraw_clamped= MIN2(0.05f, time_redraw); /* clamt the redraw time to avoid jitter in roll correction */
@@ -854,11 +920,103 @@ static int flyApply(bContext *C, FlyInfo *fly)
copy_v3_v3(fly->dvec_prev, dvec);
}
-/* moved to flyEnd() */
-
return OPERATOR_FINISHED;
}
+static int flyApply_ndof(bContext *C, FlyInfo *fly)
+{
+ // shorthand for oft-used variables
+ wmNDOFMotionData* ndof = fly->ndof;
+ const float dt = ndof->dt;
+ RegionView3D* rv3d = fly->rv3d;
+
+ const int shouldRotate = 1, shouldTranslate = 1;
+
+ float view_inv[4];
+ invert_qt_qt(view_inv, rv3d->viewquat);
+
+ if (shouldTranslate)
+ {
+ const float forward_sensitivity = 1.f;
+ const float vertical_sensitivity = 0.4f;
+ const float lateral_sensitivity = 0.6f;
+
+ float speed = 10.f; // blender units per second
+ // ^^ this is ok for default cube scene, but should scale with.. something
+
+ float trans[3] = {
+ lateral_sensitivity * ndof->tx,
+ vertical_sensitivity * ndof->ty,
+ forward_sensitivity * ndof->tz
+ };
+
+ mul_v3_fl(trans, speed * dt);
+
+ // transform motion from view to world coordinates
+ mul_qt_v3(view_inv, trans);
+
+ if (U.ndof_flag & NDOF_FLY_HELICOPTER)
+ // could also use RNA to get a simple boolean value
+ {
+ // replace world z component with device y (yes it makes sense)
+ trans[2] = speed * dt * vertical_sensitivity * ndof->ty;
+ }
+
+ // move center of view opposite of hand motion (this is camera mode, not object mode)
+ sub_v3_v3(rv3d->ofs, trans);
+
+ fly->redraw = 1;
+ }
+
+ if (shouldRotate)
+ {
+ const float turn_sensitivity = 1.f;
+
+ float rotation[4];
+ float axis[3];
+ float angle = turn_sensitivity * ndof_to_angle_axis(ndof, axis);
+
+ // transform rotation axis from view to world coordinates
+ mul_qt_v3(view_inv, axis);
+
+ // apply rotation to view
+ axis_angle_to_quat(rotation, axis, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
+
+ if (U.ndof_flag & NDOF_LOCK_HORIZON)
+ // force an upright viewpoint
+ // TODO: make this less... sudden
+ {
+ float view_horizon[3] = {1, 0, 0}; // view +x
+ float view_direction[3] = {0, 0, -1}; // view -z (into screen)
+
+ // find new inverse since viewquat has changed
+ invert_qt_qt(view_inv, rv3d->viewquat);
+
+ // transform view vectors to world coordinates
+ mul_qt_v3(view_inv, view_horizon);
+ mul_qt_v3(view_inv, view_direction);
+
+ // find difference between view & world horizons
+ // true horizon lives in world xy plane, so look only at difference in z
+ angle = -asinf(view_horizon[2]);
+
+ #ifdef NDOF_FLY_DEBUG
+ printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle));
+ #endif
+
+ // rotate view so view horizon = world horizon
+ axis_angle_to_quat(rotation, view_direction, angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation);
+ }
+
+ rv3d->view = RV3D_VIEW_USER;
+
+ fly->redraw = 1;
+ }
+
+ return OPERATOR_FINISHED;
+}
static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event)
@@ -908,7 +1066,12 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event)
flyEvent(fly, event);
- if(event->type==TIMER && event->customdata == fly->timer)
+ if (fly->ndof) // 3D mouse overrules [2D mouse + timer]
+ {
+ if (event->type==NDOF_MOTION)
+ flyApply_ndof(C, fly);
+ }
+ else if (event->type==TIMER && event->customdata == fly->timer)
flyApply(C, fly);
do_draw |= fly->redraw;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index d3886d48873..28e0e48f220 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -51,6 +51,7 @@ struct ARegionType;
struct bPoseChannel;
struct bAnimVizSettings;
struct bMotionPath;
+struct wmNDOFMotionData;
#define BL_NEAR_CLIP 0.001
@@ -72,6 +73,7 @@ void VIEW3D_OT_dolly(struct wmOperatorType *ot);
void VIEW3D_OT_zoom_camera_1_to_1(struct wmOperatorType *ot);
void VIEW3D_OT_move(struct wmOperatorType *ot);
void VIEW3D_OT_rotate(struct wmOperatorType *ot);
+void VIEW3D_OT_ndof(struct wmOperatorType *ot);
void VIEW3D_OT_view_all(struct wmOperatorType *ot);
void VIEW3D_OT_viewnumpad(struct wmOperatorType *ot);
void VIEW3D_OT_view_selected(struct wmOperatorType *ot);
@@ -91,6 +93,8 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
void VIEW3D_OT_drawtype(struct wmOperatorType *ot);
void view3d_boxview_copy(ScrArea *sa, ARegion *ar);
+void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]);
+float ndof_to_angle_axis(struct wmNDOFMotionData* ndof, float axis[3]);
/* view3d_fly.c */
void view3d_keymap(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 05ef79a9f29..2dd560a6408 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -64,6 +64,7 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_zoom);
WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1);
WM_operatortype_append(VIEW3D_OT_dolly);
+ WM_operatortype_append(VIEW3D_OT_ndof);
WM_operatortype_append(VIEW3D_OT_view_all);
WM_operatortype_append(VIEW3D_OT_viewnumpad);
WM_operatortype_append(VIEW3D_OT_view_orbit);
@@ -161,6 +162,16 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, 0, 0)->ptr, "center", 0); /* only without camera view */
RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "center", 1);
+ /* 3D mouse */
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof", NDOF_MOTION, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
+ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
+
/* numpad view hotkeys*/
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index ae57cf3f80b..a94c10a7aa0 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -365,7 +365,7 @@ typedef struct UserDef {
short recent_files; /* maximum number of recently used files to remember */
short smooth_viewtx; /* miliseconds to spend spinning the view */
short glreslimit;
- short ndof_pan, ndof_rotate;
+/* short ndof_pan, ndof_rotate; */
short curssize;
short color_picker_type;
short ipo_new; /* interpolation mode for newly added F-Curves */
@@ -376,6 +376,10 @@ typedef struct UserDef {
short widget_unit; /* defaults to 20 for 72 DPI setting */
short anisotropic_filter;
+ /*short pad[3]; */
+
+ float ndof_sensitivity; /* overall sensitivity of 3D mouse */
+ int ndof_flag; /* flags for 3D mouse */
char versemaster[160];
char verseuser[160];
@@ -384,7 +388,7 @@ typedef struct UserDef {
short autokey_mode; /* autokeying mode */
short autokey_flag; /* flags for autokeying */
- short text_render, pad9; /*options for text rendering*/
+ short text_render, pad9[3]; /*options for text rendering*/
struct ColorBand coba_weight; /* from texture.h */
@@ -577,6 +581,17 @@ extern UserDef U; /* from blenkernel blender.c */
#define TH_OLDSKOOL 3
#define TH_SHADED 4
+/* ndof_flag (3D mouse options) */
+#define NDOF_SHOW_GUIDE (1 << 0)
+#define NDOF_FLY_HELICOPTER (1 << 1)
+#define NDOF_LOCK_HORIZON (1 << 2)
+/* the following might not need to be saved between sessions,
+ but they do need to live somewhere accessible...
+#define NDOF_SHOULD_PAN (1 << 3)
+#define NDOF_SHOULD_ZOOM (1 << 4)
+#define NDOF_SHOULD_ROTATE (1 << 5)
+*/
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 4d1e1f175f2..664cb7732f9 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -2737,7 +2737,9 @@ static void rna_def_userdef_input(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "dragthreshold");
RNA_def_property_range(prop, 3, 40);
RNA_def_property_ui_text(prop, "Drag Threshold", "Amount of pixels you have to drag before dragging UI items happens");
-
+
+ /* 3D mouse settings */
+/*
prop= RNA_def_property(srna, "ndof_pan_speed", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "ndof_pan");
RNA_def_property_range(prop, 0, 200);
@@ -2747,7 +2749,24 @@ static void rna_def_userdef_input(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "ndof_rotate");
RNA_def_property_range(prop, 0, 200);
RNA_def_property_ui_text(prop, "NDof Rotation Speed", "The overall rotation speed of an NDOF device, as percent of standard");
-
+*/
+ prop= RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.25f, 4.0f);
+ RNA_def_property_ui_text(prop, "3D Mouse Sensitivity", "Baseline sensitivity of the 3D Mouse");
+
+ prop= RNA_def_property(srna, "ndof_show_guide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE);
+ RNA_def_property_ui_text(prop, "Show 3D Mouse Guide", "Visualize the center and axis of rotation (or projected position in fly mode)");
+
+ prop= RNA_def_property(srna, "ndof_lock_horizon", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_LOCK_HORIZON);
+ RNA_def_property_ui_text(prop, "Lock Horizon", "Keep horizon level while flying with 3D Mouse");
+
+ prop= RNA_def_property(srna, "ndof_fly_helicopter", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER);
+ RNA_def_property_ui_text(prop, "Helicopter Fly Mode", "");
+
+
prop= RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dbl_click_time");
RNA_def_property_range(prop, 1, 1000);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 49bd3ede37d..7476410ec19 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -377,6 +377,26 @@ typedef struct wmTabletData {
float Ytilt; /* as above */
} wmTabletData;
+typedef enum { // motion progress, for modal handlers
+ P_NOT_STARTED,
+ P_STARTING, // <--
+ P_IN_PROGRESS, // <-- only these are sent for NDOF motion
+ P_FINISHING, // <--
+ P_FINISHED
+ } wmProgress;
+
+typedef struct wmNDOFMotionData {
+ /* awfully similar to GHOST_TEventNDOFMotionData... */
+ // Each component normally ranges from -1 to +1, but can exceed that.
+ // These use blender standard view coordinates, with positive rotations being CCW about the axis.
+ float tx, ty, tz; // translation
+ float rx, ry, rz; // rotation:
+ // axis = (rx,ry,rz).normalized
+ // amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg]
+ float dt; // time since previous NDOF Motion event
+ wmProgress progress; // is this the first event, the last, or one of many in between?
+} wmNDOFMotionData;
+
typedef struct wmTimer {
struct wmTimer *next, *prev;
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index ce3830b059c..26d72906ece 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2309,6 +2309,28 @@ static void update_tablet_data(wmWindow *win, wmEvent *event)
}
}
+/* adds customdata to event */
+static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* ghost)
+{
+ wmNDOFMotionData* data = MEM_mallocN(sizeof(wmNDOFMotionData), "customdata NDOF");
+
+ data->tx = ghost->tx;
+ data->ty = ghost->ty;
+ data->tz = ghost->tz;
+
+ data->rx = ghost->rx;
+ data->ry = ghost->ry;
+ data->rz = ghost->rz;
+
+ data->dt = ghost->dt;
+
+ data->progress = (wmProgress) ghost->progress;
+
+ event->custom = EVT_DATA_NDOF_MOTION;
+ event->customdata = data;
+ event->customdatafree = 1;
+}
+
/* imperfect but probably usable... draw/enable drags to other windows */
static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *evt)
{
@@ -2355,7 +2377,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
{
wmWindow *owin;
wmEvent event, *evt= win->eventstate;
-
+
/* initialize and copy state (only mouse x y and modifiers) */
event= *evt;
@@ -2557,6 +2579,36 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
break;
}
+ case GHOST_kEventNDOFMotion: {
+ event.type = NDOF_MOTION;
+ attach_ndof_data(&event, customdata);
+ wm_event_add(win, &event);
+
+ break;
+ }
+
+ case GHOST_kEventNDOFButton: {
+ GHOST_TEventNDOFButtonData* e = customdata;
+
+ event.type = NDOF_BUTTON_NONE + e->button;
+
+ switch (e->action) {
+ case GHOST_kPress:
+ event.val = KM_PRESS;
+ break;
+ case GHOST_kRelease:
+ event.val = KM_RELEASE;
+ break;
+ }
+
+ event.custom = 0;
+ event.customdata = NULL;
+
+ wm_event_add(win, &event);
+
+ break;
+ }
+
case GHOST_kEventUnknown:
case GHOST_kNumEventTypes:
break;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 29afdb570ea..32d2adffb01 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1411,6 +1411,113 @@ static void WM_OT_search_menu(wmOperatorType *ot)
ot->poll= wm_search_menu_poll;
}
+// BEGIN ndof menu -- experimental!
+
+#if 0
+static uiBlock* wm_block_ndof_menu_1st(bContext* C, ARegion* ar, void* UNUSED(arg_op))
+{
+ uiBlock* block;
+ uiBut* but;
+
+ block = uiBeginBlock(C, ar, "ndof_popup_menu", UI_EMBOSS);
+ uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT);
+// uiBlockSetDirection(block, UI_DOWN);
+// uiBlockBeginAlign(block);
+
+ // uiItemBooleanO(block->curlayout, "enable pan/zoom", ICON_NDOF_TRANS, "toggle_ndof_pan_zoom_enabled", "ndof_pan_zoom_enabled", 1);
+ // uiBlock is used as an opaque type in this file, so can't use members...
+
+ int foo = 333;
+ uiDefButI(block, TOG, 0, "foo", 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, &foo, 0.f, 1.f, 0.1f, 0.9f, "15%");
+ // uiDefBut(block, TOG, 0, "enable pan/zoom", 0, 0, 10, 10, NULL, 0.f, 1.f, 0.f, 1.f, "don't talk to strangers");
+
+// uiBlockEndAlign(block);
+// uiBoundsBlock(block, 6);
+ uiEndBlock(C, block);
+
+ return block;
+}
+
+static int wm_ndof_menu_poll(bContext *C)
+{
+ if(CTX_wm_window(C)==NULL)
+ return 0;
+
+ // if menu is already pulled up, another button press should dismiss it
+ // not sure if that behavior should go here or elsewhere...
+
+ puts("ndof: menu poll");
+ return 1;
+}
+
+static int wm_ndof_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
+{
+ puts("ndof: menu exec");
+ return OPERATOR_FINISHED;
+}
+#endif
+
+static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+{
+ uiPupMenuInvoke(C,"VIEW3D_MT_ndof_settings");
+
+ return OPERATOR_CANCELLED; // <-- correct?
+
+/*
+// uiPupMenuNotice(C, "Hello!"); // <-- this works
+// uiPupBlock(C, wm_block_ndof_menu, op); // <-- no luck!
+// ui_popup_menu_create(C, NULL, NULL, NULL, NULL, "Hello!"); // <-- this works
+
+ uiPopupMenu* pup = uiPupMenuBegin(C,"3D mouse settings",ICON_NDOF_TURN);
+ uiLayout* layout = uiPupMenuLayout(pup);
+
+ uiItemS(layout); // separator
+ uiItemFloatO(layout, "sensitivity", 0, 0, "ndof_sensitivity", 1.f);
+ // do I have to look specifically in "UserPreferences" for ndof_sensitivity property?
+
+ // trial & error -- ok, mostly error
+// uiItemBooleanO(layout, "enable pan/zoom", ICON_NDOF_TRANS, "ndof_toggle_pan_zoom_enabled", "ndof_pan_zoom_enabled", 1);
+// uiItemBooleanO(layout, "enable rotation", ICON_NDOF_TURN, "ndof_toggle_rotation_enabled", "ndof_rotation_enabled", 1);
+// uiItemV(layout,"sensitivity",ICON_NDOF_TRANS, 1);
+
+ printf("ndof: menu invoked in ");
+
+ switch (CTX_wm_area(C)->spacetype) // diff spaces can have diff 3d mouse options
+ {
+ case SPACE_VIEW3D:
+ puts("3D area");
+ uiItemS(layout);
+ uiItemL(layout, "3D navigation mode", 0);
+ uiItemBooleanO(layout, "helicopter", ICON_NDOF_FLY, 0, "ndof_fly_helicopter", 1);
+ uiItemBooleanO(layout, "lock horizon", ICON_NDOF_DOM, 0, "ndof_lock_horizon", 1);
+ break;
+ case SPACE_IMAGE:
+ puts("image area");
+ break;
+ default:
+ puts("some iNDOFferent area");
+ }
+
+ //uiBlock* block = uiLayoutGetBlock(layout);
+ //int foo = 1;
+ //uiDefButI(block, TOG, 0, "foo", 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, &foo, 0.f, 1.f, 0.1f, 0.9f, "15%");
+
+ uiPupMenuEnd(C,pup);
+*/
+}
+
+static void WM_OT_ndof_menu(wmOperatorType *ot)
+{
+ puts("ndof: registering menu operator");
+
+ ot->name = "NDOF Menu";
+ ot->idname = "WM_OT_ndof_menu";
+
+ ot->invoke = wm_ndof_menu_invoke;
+}
+
+// END ndof menu
+
static int wm_call_menu_exec(bContext *C, wmOperator *op)
{
char idname[BKE_ST_MAXNAME];
@@ -3453,6 +3560,7 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_debug_menu);
WM_operatortype_append(WM_OT_splash);
WM_operatortype_append(WM_OT_search_menu);
+ WM_operatortype_append(WM_OT_ndof_menu);
WM_operatortype_append(WM_OT_call_menu);
WM_operatortype_append(WM_OT_radial_control);
#if defined(WIN32)
@@ -3675,7 +3783,9 @@ void wm_window_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT|KM_CTRL, 0);
WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0);
-
+
+ WM_keymap_add_item(keymap, "WM_OT_ndof_menu", NDOF_BUTTON_MENU, KM_PRESS, 0, 0);
+
/* Space switching */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 9b1695be67a..7d6010786d2 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -621,12 +621,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
if (!ghostwin) {
// XXX - should be checked, why are we getting an event here, and
// what is it?
-
+ puts("<!> event has no window");
return 1;
} else if (!GHOST_ValidWindow(g_system, ghostwin)) {
// XXX - should be checked, why are we getting an event here, and
// what is it?
-
+ puts("<!> event has invalid window");
return 1;
} else {
win= GHOST_GetWindowUserData(ghostwin);
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index ee080e7c0aa..210dd902b99 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -45,6 +45,7 @@
#define EVT_DATA_GESTURE 2
#define EVT_DATA_TIMER 3
#define EVT_DATA_LISTBASE 4
+#define EVT_DATA_NDOF_MOTION 5
/* tablet active, matches GHOST_TTabletMode */
#define EVT_TABLET_NONE 0
@@ -78,6 +79,55 @@
#define INBETWEEN_MOUSEMOVE 17
+/* NDOF (from SpaceNavigator & friends)
+ These should be kept in sync with GHOST_NDOFManager.h
+ Ordering matters, exact values do not. */
+
+#define NDOF_MOTION 400
+
+enum {
+ // used internally, never sent
+ NDOF_BUTTON_NONE = NDOF_MOTION,
+ // these two are available from any 3Dconnexion device
+ NDOF_BUTTON_MENU,
+ NDOF_BUTTON_FIT,
+ // standard views
+ NDOF_BUTTON_TOP,
+ NDOF_BUTTON_BOTTOM,
+ NDOF_BUTTON_LEFT,
+ NDOF_BUTTON_RIGHT,
+ NDOF_BUTTON_FRONT,
+ NDOF_BUTTON_BACK,
+ // more views
+ NDOF_BUTTON_ISO1,
+ NDOF_BUTTON_ISO2,
+ // 90 degree rotations
+ NDOF_BUTTON_ROLL_CW,
+ NDOF_BUTTON_ROLL_CCW,
+ NDOF_BUTTON_SPIN_CW,
+ NDOF_BUTTON_SPIN_CCW,
+ NDOF_BUTTON_TILT_CW,
+ NDOF_BUTTON_TILT_CCW,
+ // device control
+ NDOF_BUTTON_ROTATE,
+ NDOF_BUTTON_PANZOOM,
+ NDOF_BUTTON_DOMINANT,
+ NDOF_BUTTON_PLUS,
+ NDOF_BUTTON_MINUS,
+ // general-purpose buttons
+ NDOF_BUTTON_1,
+ NDOF_BUTTON_2,
+ NDOF_BUTTON_3,
+ NDOF_BUTTON_4,
+ NDOF_BUTTON_5,
+ NDOF_BUTTON_6,
+ NDOF_BUTTON_7,
+ NDOF_BUTTON_8,
+ NDOF_BUTTON_9,
+ NDOF_BUTTON_10,
+ };
+
+
/* SYSTEM : 0x01xx */
#define INPUTCHANGE 0x0103 /* input connected or disconnected */
#define WINDEACTIVATE 0x0104 /* window is deactivated, focus lost */