3D View: support canceling viewport operations

Support Esc / RMB to cancel dolly, move, rotate & zoom.
Previously only roll could be canceled.

This can be useful to temporary orbit away from the camera or an
orthographic view without having to manually set it back.
This commit is contained in:
Campbell Barton 2022-12-07 17:41:02 +11:00
parent dcd4eb4c25
commit 0b85d6a030
Notes: blender-bot 2023-04-18 06:42:09 +02:00
Referenced by issue #107028, Viewport camera movement gets reset by RMB (zoom) when using industry compatible keybinds preset
6 changed files with 107 additions and 3 deletions

View File

@ -298,6 +298,7 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
else {
vod->use_dyn_ofs = false;
}
vod->init.persp = rv3d->persp;
if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->region)) {
@ -311,7 +312,9 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
* we may want to make this optional but for now its needed always */
ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
vod->init.persp = rv3d->persp;
vod->init.persp_with_auto_persp_applied = rv3d->persp;
vod->init.view = rv3d->view;
vod->init.view_axis_roll = rv3d->view_axis_roll;
vod->init.dist = rv3d->dist;
vod->init.camzoom = rv3d->camzoom;
copy_qt_qt(vod->init.quat, rv3d->viewquat);
@ -332,6 +335,10 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
copy_qt_qt(vod->curr.viewquat, rv3d->viewquat);
copy_v3_v3(vod->init.ofs_lock, rv3d->ofs_lock);
vod->init.camdx = rv3d->camdx;
vod->init.camdy = rv3d->camdy;
if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) {
float ofs[3];
if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
@ -585,6 +592,23 @@ void viewmove_apply(ViewOpsData *vod, int x, int y)
ED_region_tag_redraw(vod->region);
}
void viewmove_apply_reset(ViewOpsData *vod)
{
if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
vod->rv3d->camdx = vod->init.camdx;
vod->rv3d->camdy = vod->init.camdy;
}
else if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) {
copy_v2_v2(vod->rv3d->ofs_lock, vod->init.ofs_lock);
}
else {
copy_v3_v3(vod->rv3d->ofs, vod->init.ofs);
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->area, vod->region);
}
}
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -97,9 +97,14 @@ typedef struct ViewOpsData {
/** #wmEvent.type that triggered the operator. */
int event_type;
float ofs[3];
/** #RegionView3D.ofs_lock */
float ofs_lock[2];
/** Initial distance to 'ofs'. */
float zfac;
/** Camera offset. */
float camdx, camdy;
/** Trackball rotation only. */
float trackvec[3];
/** Dolly only. */
@ -109,7 +114,13 @@ typedef struct ViewOpsData {
* #RegionView3D.persp set after auto-perspective is applied.
* If we want the value before running the operator, add a separate member.
*/
char persp_with_auto_persp_applied;
/** #RegionView3D.persp set after before auto-perspective is applied. */
char persp;
/** #RegionView3D.view */
char view;
/** #RegionView3D.view_axis_roll */
char view_axis_roll;
/** Used for roll */
struct Dial *dial;
@ -147,6 +158,7 @@ bool view3d_zoom_or_dolly_poll(struct bContext *C);
enum eViewOpsFlag viewops_flag_from_prefs(void);
void calctrackballvec(const struct rcti *rect, const int event_xy[2], float r_dir[3]);
void viewmove_apply(ViewOpsData *vod, int x, int y);
void viewmove_apply_reset(ViewOpsData *vod);
void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
const float ofs_old[3],
const float viewquat_old[4],

View File

@ -167,6 +167,11 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
switch (event_code) {
@ -182,6 +187,13 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
/* Note this does not remove auto-keys on locked cameras. */
copy_v3_v3(vod->rv3d->ofs, vod->init.ofs);
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
if (use_autokey) {

View File

@ -4,6 +4,8 @@
* \ingroup spview3d
*/
#include "BLI_math_vector.h"
#include "BKE_context.h"
#include "WM_api.h"
@ -126,6 +128,11 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
switch (event_code) {
@ -141,6 +148,12 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
viewmove_apply_reset(vod);
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
if (use_autokey) {

View File

@ -182,7 +182,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
}
}
else if (U.uiflag & USER_AUTOPERSP) {
rv3d->persp = vod->init.persp;
rv3d->persp = vod->init.persp_with_auto_persp_applied;
}
}
@ -338,7 +338,7 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_APPLY;
break;
case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
vod->rv3d->persp = vod->init.persp;
vod->rv3d->persp = vod->init.persp_with_auto_persp_applied;
vod->axis_snap = false;
event_code = VIEW_APPLY;
break;
@ -361,6 +361,11 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
switch (event_code) {
@ -376,6 +381,25 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
/* Note this does not remove auto-keys on locked cameras. */
copy_qt_qt(vod->rv3d->viewquat, vod->init.quat);
/* The offset may have change when rotating around objects or last-brush. */
copy_v3_v3(vod->rv3d->ofs, vod->init.ofs);
/* The dist may have changed when orbiting from a camera view.
* In this case the `dist` is calculated based on the camera relative to the `ofs`. */
vod->rv3d->dist = vod->init.dist;
vod->rv3d->persp = vod->init.persp;
vod->rv3d->view = vod->init.view;
vod->rv3d->view_axis_roll = vod->init.view_axis_roll;
/* NOTE: there is no need to restore "last" values (as set by #ED_view3d_lastview_store). */
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
if (use_autokey) {

View File

@ -408,6 +408,11 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
switch (event_code) {
@ -428,6 +433,20 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
/* Note this does not remove auto-keys on locked cameras. */
vod->rv3d->dist = vod->init.dist;
/* The offset may have change when zooming to mouse position. */
copy_v3_v3(vod->rv3d->ofs, vod->init.ofs);
vod->rv3d->camzoom = vod->init.camzoom;
/* Zoom to mouse position in camera view changes these values. */
vod->rv3d->camdx = vod->init.camdx;
vod->rv3d->camdy = vod->init.camdy;
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
if (use_autokey) {