Transform: Support navigation from NDOF devices

This commit implements the `VIEW3D_OT_ndof_orbit`,
`VIEW3D_OT_ndof_orbit_zoom`, `VIEW3D_OT_ndof_pan` and
`VIEW3D_OT_ndof_all` operators to the `ED_view3d_navigation_`
utility so that these operations can be used in the transform
operators.

Pull Request: https://projects.blender.org/blender/blender/pulls/109792
This commit is contained in:
Germano Cavalcante
2023-07-10 14:57:40 +02:00
committed by Germano Cavalcante
parent 113004687d
commit 37d1d4cb07
3 changed files with 99 additions and 66 deletions

View File

@@ -75,6 +75,10 @@ const char *viewops_operator_idname_get(eV3D_OpMode nav_type)
return "VIEW3D_OT_ndof_orbit";
case V3D_OP_MODE_NDOF_ORBIT_ZOOM:
return "VIEW3D_OT_ndof_orbit_zoom";
case V3D_OP_MODE_NDOF_PAN:
return "VIEW3D_OT_ndof_pan";
case V3D_OP_MODE_NDOF_ALL:
return "VIEW3D_OT_ndof_all";
#endif
case V3D_OP_MODE_NONE:
break;
@@ -186,9 +190,18 @@ static int view3d_navigation_invoke_generic(bContext *C,
return viewrotate_invoke_impl(vod, event);
case V3D_OP_MODE_MOVE:
return viewmove_invoke_impl(vod, event);
case V3D_OP_MODE_VIEW_PAN: {
case V3D_OP_MODE_VIEW_PAN:
return viewpan_invoke_impl(vod, ptr);
}
#ifdef WITH_INPUT_NDOF
case V3D_OP_MODE_NDOF_ORBIT:
return ndof_orbit_invoke_impl(C, vod, event);
case V3D_OP_MODE_NDOF_ORBIT_ZOOM:
return ndof_orbit_zoom_invoke_impl(C, vod, event);
case V3D_OP_MODE_NDOF_PAN:
return ndof_pan_invoke_impl(C, vod, event);
case V3D_OP_MODE_NDOF_ALL:
return ndof_all_invoke_impl(C, vod, event);
#endif
default:
break;
}
@@ -530,7 +543,7 @@ static void viewops_data_init_context(bContext *C, ViewOpsData *vod)
vod->rv3d = static_cast<RegionView3D *>(vod->region->regiondata);
}
static void viewops_data_state_capture(ViewOpsData *vod)
static void viewops_data_state_capture(ViewOpsData *vod, const bool calc_dist)
{
Depsgraph *depsgraph = vod->depsgraph;
View3D *v3d = vod->v3d;
@@ -539,7 +552,7 @@ static void viewops_data_state_capture(ViewOpsData *vod)
/* Set the view from the camera, if view locking is enabled.
* we may want to make this optional but for now its needed always.
* NOTE: This changes the value of `rv3d->dist`. */
ED_view3d_camera_lock_init(depsgraph, v3d, rv3d);
ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, calc_dist);
copy_v3_v3(vod->init.ofs, rv3d->ofs);
copy_v3_v3(vod->init.ofs_lock, rv3d->ofs_lock);
@@ -635,6 +648,7 @@ static void viewops_data_init_navigation(bContext *C,
RegionView3D *rv3d = vod->rv3d;
eViewOpsFlag viewops_flag = viewops_flag_from_prefs();
bool calc_rv3d_dist = true;
if (use_cursor_init) {
viewops_flag |= VIEWOPS_FLAG_USE_MOUSE_INIT;
@@ -653,7 +667,10 @@ static void viewops_data_init_navigation(bContext *C,
#ifdef WITH_INPUT_NDOF
case V3D_OP_MODE_NDOF_ORBIT:
case V3D_OP_MODE_NDOF_ORBIT_ZOOM:
case V3D_OP_MODE_NDOF_PAN:
case V3D_OP_MODE_NDOF_ALL:
viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
calc_rv3d_dist = false;
break;
#endif
default:
@@ -693,7 +710,7 @@ static void viewops_data_init_navigation(bContext *C,
vod->use_dyn_ofs = false;
}
viewops_data_state_capture(vod);
viewops_data_state_capture(vod, calc_rv3d_dist);
if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->region)) {
@@ -2074,6 +2091,8 @@ static int view3d_navigation_invoke(
#ifdef WITH_INPUT_NDOF
case V3D_OP_MODE_NDOF_ORBIT:
case V3D_OP_MODE_NDOF_ORBIT_ZOOM:
case V3D_OP_MODE_NDOF_PAN:
case V3D_OP_MODE_NDOF_ALL:
#endif
case V3D_OP_MODE_NONE:
break;

View File

@@ -44,12 +44,14 @@ typedef enum eV3D_OpMode {
#ifdef WITH_INPUT_NDOF
V3D_OP_MODE_NDOF_ORBIT,
V3D_OP_MODE_NDOF_ORBIT_ZOOM,
V3D_OP_MODE_NDOF_PAN,
V3D_OP_MODE_NDOF_ALL,
#endif
} eV3D_OpMode;
#ifndef WITH_INPUT_NDOF
# define V3D_OP_MODE_LEN V3D_OP_MODE_DOLLY + 1
#else
# define V3D_OP_MODE_LEN V3D_OP_MODE_NDOF_ORBIT_ZOOM + 1
# define V3D_OP_MODE_LEN V3D_OP_MODE_NDOF_ALL + 1
#endif
enum eV3D_OpPropFlag {
@@ -272,6 +274,11 @@ void VIEW3D_OT_move(struct wmOperatorType *ot);
#ifdef WITH_INPUT_NDOF
struct wmNDOFMotionData;
int ndof_orbit_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event);
int ndof_orbit_zoom_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event);
int ndof_pan_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event);
int ndof_all_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event);
/**
* Called from both fly mode and walk mode,
*/

View File

@@ -356,14 +356,11 @@ void view3d_ndof_fly(const wmNDOFMotionData *ndof,
* 2D orthographic style NDOF navigation within the camera view.
* Support navigating the camera view instead of leaving the camera-view and navigating in 3D.
*/
static int view3d_ndof_cameraview_pan_zoom(bContext *C, const wmEvent *event)
static int view3d_ndof_cameraview_pan_zoom(ViewOpsData *vod, const wmNDOFMotionData *ndof)
{
const wmNDOFMotionData *ndof = event->customdata;
View3D *v3d = CTX_wm_view3d(C);
ARegion *region = CTX_wm_region(C);
RegionView3D *rv3d = region->regiondata;
ED_view3d_smooth_view_force_finish(C, v3d, region);
View3D *v3d = vod->v3d;
ARegion *region = vod->region;
RegionView3D *rv3d = vod->rv3d;
if (v3d->camera && (rv3d->persp == RV3D_CAMOB) && (v3d->flag2 & V3D_LOCK_CAMERA) == 0) {
/* pass */
@@ -423,32 +420,22 @@ static int view3d_ndof_cameraview_pan_zoom(bContext *C, const wmEvent *event)
/** \name NDOF Orbit/Translate Operator
* \{ */
static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int ndof_orbit_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewOpsData *vod;
View3D *v3d;
RegionView3D *rv3d;
const Depsgraph *depsgraph = vod->depsgraph;
View3D *v3d = vod->v3d;
RegionView3D *rv3d = vod->rv3d;
char xform_flag = 0;
const wmNDOFMotionData *ndof = event->customdata;
vod = op->customdata = viewops_data_create(C, event, V3D_OP_MODE_NDOF_ORBIT, false);
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
v3d = vod->v3d;
rv3d = vod->rv3d;
/* off by default, until changed later this function */
rv3d->rot_angle = 0.0f;
ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress != P_FINISHING) {
const bool has_rotation = ndof_has_rotate(ndof, rv3d);
/* if we can't rotate, fallback to translate (locked axis views) */
@@ -475,18 +462,24 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(vod->region);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
return view3d_navigate_invoke_impl(C, op, event, V3D_OP_MODE_NDOF_ORBIT);
}
void VIEW3D_OT_ndof_orbit(wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Orbit View";
ot->description = "Orbit the view using the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_orbit";
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_NDOF_ORBIT);
/* api callbacks */
ot->invoke = ndof_orbit_invoke;
@@ -502,39 +495,28 @@ void VIEW3D_OT_ndof_orbit(wmOperatorType *ot)
/** \name NDOF Orbit/Zoom Operator
* \{ */
static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int ndof_orbit_zoom_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
const wmNDOFMotionData *ndof = event->customdata;
if (U.ndof_flag & NDOF_CAMERA_PAN_ZOOM) {
const int camera_retval = view3d_ndof_cameraview_pan_zoom(C, event);
const int camera_retval = view3d_ndof_cameraview_pan_zoom(vod, ndof);
if (camera_retval != OPERATOR_PASS_THROUGH) {
return camera_retval;
}
}
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewOpsData *vod;
View3D *v3d;
RegionView3D *rv3d;
View3D *v3d = vod->v3d;
RegionView3D *rv3d = vod->rv3d;
char xform_flag = 0;
const wmNDOFMotionData *ndof = event->customdata;
vod = op->customdata = viewops_data_create(C, event, V3D_OP_MODE_NDOF_ORBIT_ZOOM, false);
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
v3d = vod->v3d;
rv3d = vod->rv3d;
/* off by default, until changed later this function */
rv3d->rot_angle = 0.0f;
ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress == P_FINISHING) {
/* pass */
}
@@ -587,7 +569,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
}
ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
ED_view3d_camera_lock_sync(vod->depsgraph, v3d, rv3d);
if (xform_flag) {
ED_view3d_camera_lock_autokey(
v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE);
@@ -595,18 +577,24 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
ED_region_tag_redraw(vod->region);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_FINISHED;
}
static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
return view3d_navigate_invoke_impl(C, op, event, V3D_OP_MODE_NDOF_ORBIT_ZOOM);
}
void VIEW3D_OT_ndof_orbit_zoom(wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Orbit View with Zoom";
ot->description = "Orbit and zoom the view using the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_NDOF_ORBIT_ZOOM);
/* api callbacks */
ot->invoke = ndof_orbit_zoom_invoke;
@@ -622,23 +610,25 @@ void VIEW3D_OT_ndof_orbit_zoom(wmOperatorType *ot)
/** \name NDOF Pan/Zoom Operator
* \{ */
static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
int ndof_pan_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
const wmNDOFMotionData *ndof = event->customdata;
if (U.ndof_flag & NDOF_CAMERA_PAN_ZOOM) {
const int camera_retval = view3d_ndof_cameraview_pan_zoom(C, event);
const int camera_retval = view3d_ndof_cameraview_pan_zoom(vod, ndof);
if (camera_retval != OPERATOR_PASS_THROUGH) {
return camera_retval;
}
}
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
const wmNDOFMotionData *ndof = event->customdata;
const Depsgraph *depsgraph = vod->depsgraph;
View3D *v3d = vod->v3d;
RegionView3D *rv3d = vod->rv3d;
ARegion *region = vod->region;
char xform_flag = 0;
const bool has_translate = ndof_has_translate(ndof, v3d, rv3d);
@@ -654,8 +644,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress != P_FINISHING) {
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
ScrArea *area = vod->area;
if (has_translate || has_zoom) {
view3d_ndof_pan_zoom(ndof, area, region, has_translate, has_zoom);
@@ -668,17 +657,26 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, xform_flag & HAS_TRANSLATE);
}
ED_region_tag_redraw(CTX_wm_region(C));
ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
static int ndof_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
return view3d_navigate_invoke_impl(C, op, event, V3D_OP_MODE_NDOF_PAN);
}
void VIEW3D_OT_ndof_pan(wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Pan View";
ot->description = "Pan the view with the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_pan";
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_NDOF_PAN);
/* api callbacks */
ot->invoke = ndof_pan_invoke;
@@ -697,7 +695,7 @@ void VIEW3D_OT_ndof_pan(wmOperatorType *ot)
/**
* wraps #ndof_orbit_zoom but never restrict to orbit.
*/
static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int ndof_all_invoke_impl(bContext *C, ViewOpsData *vod, const wmEvent *event)
{
/* weak!, but it works */
const int ndof_flag = U.ndof_flag;
@@ -705,19 +703,28 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
U.ndof_flag &= ~NDOF_MODE_ORBIT;
ret = ndof_orbit_zoom_invoke(C, op, event);
ret = ndof_orbit_zoom_invoke_impl(C, vod, event);
U.ndof_flag = ndof_flag;
return ret;
}
static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
return view3d_navigate_invoke_impl(C, op, event, V3D_OP_MODE_NDOF_ALL);
}
void VIEW3D_OT_ndof_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "NDOF Transform View";
ot->description = "Pan and rotate the view with the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_all";
ot->idname = viewops_operator_idname_get(V3D_OP_MODE_NDOF_ALL);
/* api callbacks */
ot->invoke = ndof_all_invoke;