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.
639 lines
20 KiB
C
639 lines
20 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup spview3d
|
|
*/
|
|
|
|
#include "BLI_math.h"
|
|
#include "BLI_rect.h"
|
|
|
|
#include "BKE_context.h"
|
|
#include "BKE_screen.h"
|
|
|
|
#include "DEG_depsgraph_query.h"
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "ED_screen.h"
|
|
|
|
#include "PIL_time.h"
|
|
|
|
#include "view3d_intern.h"
|
|
#include "view3d_navigate.h" /* own include */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name View Zoom Operator
|
|
* \{ */
|
|
|
|
/* #viewdolly_modal_keymap has an exact copy of this, apply fixes to both. */
|
|
void viewzoom_modal_keymap(wmKeyConfig *keyconf)
|
|
{
|
|
static const EnumPropertyItem modal_items[] = {
|
|
{VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
|
|
|
|
{VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
|
|
{VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
|
|
|
|
{0, NULL, 0, NULL, NULL},
|
|
};
|
|
|
|
wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Zoom Modal");
|
|
|
|
/* This function is called for each space-type, only needs to add map once. */
|
|
if (keymap && keymap->modal_items) {
|
|
return;
|
|
}
|
|
|
|
keymap = WM_modalkeymap_ensure(keyconf, "View3D Zoom Modal", modal_items);
|
|
|
|
/* disabled mode switching for now, can re-implement better, later on */
|
|
#if 0
|
|
WM_modalkeymap_add_item(keymap,
|
|
&(const KeyMapItem_Params){
|
|
.type = LEFTMOUSE,
|
|
.value = KM_RELEASE,
|
|
.modifier = KM_ANY,
|
|
.direction = KM_ANY,
|
|
},
|
|
VIEWROT_MODAL_SWITCH_ROTATE);
|
|
WM_modalkeymap_add_item(keymap,
|
|
&(const KeyMapItem_Params){
|
|
.type = EVT_LEFTCTRLKEY,
|
|
.value = KM_RELEASE,
|
|
.modifier = KM_ANY,
|
|
.direction = KM_ANY,
|
|
},
|
|
VIEWROT_MODAL_SWITCH_ROTATE);
|
|
WM_modalkeymap_add_item(keymap,
|
|
&(const KeyMapItem_Params){
|
|
.type = EVT_LEFTSHIFTKEY,
|
|
.value = KM_PRESS,
|
|
.modifier = KM_ANY,
|
|
.direction = KM_ANY,
|
|
},
|
|
VIEWROT_MODAL_SWITCH_MOVE);
|
|
#endif
|
|
|
|
/* assign map to operators */
|
|
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
|
|
}
|
|
|
|
/**
|
|
* \param zoom_xy: Optionally zoom to window location
|
|
* (coords compatible w/ #wmEvent.xy). Use when not NULL.
|
|
*/
|
|
static void view_zoom_to_window_xy_camera(Scene *scene,
|
|
Depsgraph *depsgraph,
|
|
View3D *v3d,
|
|
ARegion *region,
|
|
float dfac,
|
|
const int zoom_xy[2])
|
|
{
|
|
RegionView3D *rv3d = region->regiondata;
|
|
const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
|
|
const float zoomfac_new = clamp_f(
|
|
zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
|
|
const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
|
|
|
|
if (zoom_xy != NULL) {
|
|
float zoomfac_px;
|
|
rctf camera_frame_old;
|
|
rctf camera_frame_new;
|
|
|
|
const float pt_src[2] = {zoom_xy[0], zoom_xy[1]};
|
|
float pt_dst[2];
|
|
float delta_px[2];
|
|
|
|
ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &camera_frame_old, false);
|
|
BLI_rctf_translate(&camera_frame_old, region->winrct.xmin, region->winrct.ymin);
|
|
|
|
rv3d->camzoom = camzoom_new;
|
|
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
|
|
|
|
ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, &camera_frame_new, false);
|
|
BLI_rctf_translate(&camera_frame_new, region->winrct.xmin, region->winrct.ymin);
|
|
|
|
BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
|
|
sub_v2_v2v2(delta_px, pt_dst, pt_src);
|
|
|
|
/* translate the camera offset using pixel space delta
|
|
* mapped back to the camera (same logic as panning in camera view) */
|
|
zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f;
|
|
|
|
rv3d->camdx += delta_px[0] / (region->winx * zoomfac_px);
|
|
rv3d->camdy += delta_px[1] / (region->winy * zoomfac_px);
|
|
CLAMP(rv3d->camdx, -1.0f, 1.0f);
|
|
CLAMP(rv3d->camdy, -1.0f, 1.0f);
|
|
}
|
|
else {
|
|
rv3d->camzoom = camzoom_new;
|
|
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \param zoom_xy: Optionally zoom to window location
|
|
* (coords compatible w/ #wmEvent.xy). Use when not NULL.
|
|
*/
|
|
static void view_zoom_to_window_xy_3d(ARegion *region, float dfac, const int zoom_xy[2])
|
|
{
|
|
RegionView3D *rv3d = region->regiondata;
|
|
const float dist_new = rv3d->dist * dfac;
|
|
|
|
if (zoom_xy != NULL) {
|
|
float dvec[3];
|
|
float tvec[3];
|
|
float tpos[3];
|
|
float xy_delta[2];
|
|
|
|
float zfac;
|
|
|
|
negate_v3_v3(tpos, rv3d->ofs);
|
|
|
|
xy_delta[0] = (float)(((zoom_xy[0] - region->winrct.xmin) * 2) - region->winx) / 2.0f;
|
|
xy_delta[1] = (float)(((zoom_xy[1] - region->winrct.ymin) * 2) - region->winy) / 2.0f;
|
|
|
|
/* Project cursor position into 3D space */
|
|
zfac = ED_view3d_calc_zfac(rv3d, tpos);
|
|
ED_view3d_win_to_delta(region, xy_delta, zfac, dvec);
|
|
|
|
/* Calculate view target position for dolly */
|
|
add_v3_v3v3(tvec, tpos, dvec);
|
|
negate_v3(tvec);
|
|
|
|
/* Offset to target position and dolly */
|
|
copy_v3_v3(rv3d->ofs, tvec);
|
|
rv3d->dist = dist_new;
|
|
|
|
/* Calculate final offset */
|
|
madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac);
|
|
}
|
|
else {
|
|
rv3d->dist = dist_new;
|
|
}
|
|
}
|
|
|
|
static float viewzoom_scale_value(const rcti *winrct,
|
|
const eViewZoom_Style viewzoom,
|
|
const bool zoom_invert,
|
|
const bool zoom_invert_force,
|
|
const int xy_curr[2],
|
|
const int xy_init[2],
|
|
const float val,
|
|
const float val_orig,
|
|
double *r_timer_lastdraw)
|
|
{
|
|
float zfac;
|
|
|
|
if (viewzoom == USER_ZOOM_CONTINUE) {
|
|
double time = PIL_check_seconds_timer();
|
|
float time_step = (float)(time - *r_timer_lastdraw);
|
|
float fac;
|
|
|
|
if (U.uiflag & USER_ZOOM_HORIZ) {
|
|
fac = (float)(xy_init[0] - xy_curr[0]);
|
|
}
|
|
else {
|
|
fac = (float)(xy_init[1] - xy_curr[1]);
|
|
}
|
|
|
|
fac /= U.dpi_fac;
|
|
|
|
if (zoom_invert != zoom_invert_force) {
|
|
fac = -fac;
|
|
}
|
|
|
|
zfac = 1.0f + ((fac / 20.0f) * time_step);
|
|
*r_timer_lastdraw = time;
|
|
}
|
|
else if (viewzoom == USER_ZOOM_SCALE) {
|
|
/* method which zooms based on how far you move the mouse */
|
|
|
|
const int ctr[2] = {
|
|
BLI_rcti_cent_x(winrct),
|
|
BLI_rcti_cent_y(winrct),
|
|
};
|
|
float len_new = (5 * U.dpi_fac) + ((float)len_v2v2_int(ctr, xy_curr) / U.dpi_fac);
|
|
float len_old = (5 * U.dpi_fac) + ((float)len_v2v2_int(ctr, xy_init) / U.dpi_fac);
|
|
|
|
/* intentionally ignore 'zoom_invert' for scale */
|
|
if (zoom_invert_force) {
|
|
SWAP(float, len_new, len_old);
|
|
}
|
|
|
|
zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val;
|
|
}
|
|
else { /* USER_ZOOM_DOLLY */
|
|
float len_new = 5 * U.dpi_fac;
|
|
float len_old = 5 * U.dpi_fac;
|
|
|
|
if (U.uiflag & USER_ZOOM_HORIZ) {
|
|
len_new += (winrct->xmax - (xy_curr[0])) / U.dpi_fac;
|
|
len_old += (winrct->xmax - (xy_init[0])) / U.dpi_fac;
|
|
}
|
|
else {
|
|
len_new += (winrct->ymax - (xy_curr[1])) / U.dpi_fac;
|
|
len_old += (winrct->ymax - (xy_init[1])) / U.dpi_fac;
|
|
}
|
|
|
|
if (zoom_invert != zoom_invert_force) {
|
|
SWAP(float, len_new, len_old);
|
|
}
|
|
|
|
zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val;
|
|
}
|
|
|
|
return zfac;
|
|
}
|
|
|
|
static float viewzoom_scale_value_offset(const rcti *winrct,
|
|
const eViewZoom_Style viewzoom,
|
|
const bool zoom_invert,
|
|
const bool zoom_invert_force,
|
|
const int xy_curr[2],
|
|
const int xy_init[2],
|
|
const int xy_offset[2],
|
|
const float val,
|
|
const float val_orig,
|
|
double *r_timer_lastdraw)
|
|
{
|
|
const int xy_curr_offset[2] = {
|
|
xy_curr[0] + xy_offset[0],
|
|
xy_curr[1] + xy_offset[1],
|
|
};
|
|
const int xy_init_offset[2] = {
|
|
xy_init[0] + xy_offset[0],
|
|
xy_init[1] + xy_offset[1],
|
|
};
|
|
return viewzoom_scale_value(winrct,
|
|
viewzoom,
|
|
zoom_invert,
|
|
zoom_invert_force,
|
|
xy_curr_offset,
|
|
xy_init_offset,
|
|
val,
|
|
val_orig,
|
|
r_timer_lastdraw);
|
|
}
|
|
|
|
static void viewzoom_apply_camera(ViewOpsData *vod,
|
|
const int xy[2],
|
|
const eViewZoom_Style viewzoom,
|
|
const bool zoom_invert,
|
|
const bool zoom_to_pos)
|
|
{
|
|
float zfac;
|
|
float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->init.camzoom) * 2.0f;
|
|
float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
|
|
|
|
zfac = viewzoom_scale_value_offset(&vod->region->winrct,
|
|
viewzoom,
|
|
zoom_invert,
|
|
true,
|
|
xy,
|
|
vod->init.event_xy,
|
|
vod->init.event_xy_offset,
|
|
zoomfac,
|
|
zoomfac_prev,
|
|
&vod->prev.time);
|
|
|
|
if (!ELEM(zfac, 1.0f, 0.0f)) {
|
|
/* calculate inverted, then invert again (needed because of camera zoom scaling) */
|
|
zfac = 1.0f / zfac;
|
|
view_zoom_to_window_xy_camera(vod->scene,
|
|
vod->depsgraph,
|
|
vod->v3d,
|
|
vod->region,
|
|
zfac,
|
|
zoom_to_pos ? vod->prev.event_xy : NULL);
|
|
}
|
|
|
|
ED_region_tag_redraw(vod->region);
|
|
}
|
|
|
|
static void viewzoom_apply_3d(ViewOpsData *vod,
|
|
const int xy[2],
|
|
const eViewZoom_Style viewzoom,
|
|
const bool zoom_invert,
|
|
const bool zoom_to_pos)
|
|
{
|
|
float zfac;
|
|
float dist_range[2];
|
|
|
|
ED_view3d_dist_range_get(vod->v3d, dist_range);
|
|
|
|
zfac = viewzoom_scale_value_offset(&vod->region->winrct,
|
|
viewzoom,
|
|
zoom_invert,
|
|
false,
|
|
xy,
|
|
vod->init.event_xy,
|
|
vod->init.event_xy_offset,
|
|
vod->rv3d->dist,
|
|
vod->init.dist,
|
|
&vod->prev.time);
|
|
|
|
if (zfac != 1.0f) {
|
|
const float zfac_min = dist_range[0] / vod->rv3d->dist;
|
|
const float zfac_max = dist_range[1] / vod->rv3d->dist;
|
|
CLAMP(zfac, zfac_min, zfac_max);
|
|
|
|
view_zoom_to_window_xy_3d(vod->region, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
|
|
}
|
|
|
|
/* these limits were in old code too */
|
|
CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
|
|
|
|
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
|
|
view3d_boxview_sync(vod->area, vod->region);
|
|
}
|
|
|
|
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
|
|
|
|
ED_region_tag_redraw(vod->region);
|
|
}
|
|
|
|
static void viewzoom_apply(ViewOpsData *vod,
|
|
const int xy[2],
|
|
const eViewZoom_Style viewzoom,
|
|
const bool zoom_invert,
|
|
const bool zoom_to_pos)
|
|
{
|
|
if ((vod->rv3d->persp == RV3D_CAMOB) &&
|
|
(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) {
|
|
viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
|
|
}
|
|
else {
|
|
viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
|
|
}
|
|
}
|
|
|
|
static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|
{
|
|
ViewOpsData *vod = op->customdata;
|
|
short event_code = VIEW_PASS;
|
|
bool use_autokey = false;
|
|
int ret = OPERATOR_RUNNING_MODAL;
|
|
|
|
/* Execute the events. */
|
|
if (event->type == EVT_MODAL_MAP) {
|
|
switch (event->val) {
|
|
case VIEW_MODAL_CONFIRM:
|
|
event_code = VIEW_CONFIRM;
|
|
break;
|
|
case VIEWROT_MODAL_SWITCH_MOVE:
|
|
WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
|
|
event_code = VIEW_CONFIRM;
|
|
break;
|
|
case VIEWROT_MODAL_SWITCH_ROTATE:
|
|
WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
|
|
event_code = VIEW_CONFIRM;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (event->type == MOUSEMOVE) {
|
|
event_code = VIEW_APPLY;
|
|
}
|
|
else if (event->type == TIMER) {
|
|
if (event->customdata == vod->timer) {
|
|
/* Continuous zoom. */
|
|
event_code = VIEW_APPLY;
|
|
}
|
|
}
|
|
else if (event->type == vod->init.event_type) {
|
|
if (event->val == KM_RELEASE) {
|
|
event_code = VIEW_CONFIRM;
|
|
}
|
|
}
|
|
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
|
|
if (event->val == KM_PRESS) {
|
|
event_code = VIEW_CANCEL;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (event_code) {
|
|
case VIEW_APPLY: {
|
|
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
|
viewzoom_apply(vod,
|
|
event->xy,
|
|
(eViewZoom_Style)U.viewzoom,
|
|
(U.uiflag & USER_ZOOM_INVERT) != 0,
|
|
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
|
|
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
|
use_autokey = true;
|
|
}
|
|
break;
|
|
}
|
|
case VIEW_CONFIRM: {
|
|
use_autokey = true;
|
|
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) {
|
|
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
|
}
|
|
|
|
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
|
|
if (ret & OPERATOR_FINISHED) {
|
|
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
|
|
}
|
|
viewops_data_free(C, op->customdata);
|
|
op->customdata = NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int viewzoom_exec(bContext *C, wmOperator *op)
|
|
{
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
|
Scene *scene = CTX_data_scene(C);
|
|
View3D *v3d;
|
|
RegionView3D *rv3d;
|
|
ScrArea *area;
|
|
ARegion *region;
|
|
bool use_cam_zoom;
|
|
float dist_range[2];
|
|
|
|
const int delta = RNA_int_get(op->ptr, "delta");
|
|
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
|
|
|
if (op->customdata) {
|
|
ViewOpsData *vod = op->customdata;
|
|
|
|
area = vod->area;
|
|
region = vod->region;
|
|
}
|
|
else {
|
|
area = CTX_wm_area(C);
|
|
region = CTX_wm_region(C);
|
|
}
|
|
|
|
v3d = area->spacedata.first;
|
|
rv3d = region->regiondata;
|
|
|
|
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
|
|
!(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
|
|
|
|
int zoom_xy_buf[2];
|
|
const int *zoom_xy = NULL;
|
|
if (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
|
|
zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") :
|
|
region->winx / 2;
|
|
zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") :
|
|
region->winy / 2;
|
|
zoom_xy = zoom_xy_buf;
|
|
}
|
|
|
|
ED_view3d_dist_range_get(v3d, dist_range);
|
|
|
|
if (delta < 0) {
|
|
const float step = 1.2f;
|
|
if (use_cam_zoom) {
|
|
view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
|
|
}
|
|
else {
|
|
if (rv3d->dist < dist_range[1]) {
|
|
view_zoom_to_window_xy_3d(region, step, zoom_xy);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
const float step = 1.0f / 1.2f;
|
|
if (use_cam_zoom) {
|
|
view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
|
|
}
|
|
else {
|
|
if (rv3d->dist > dist_range[0]) {
|
|
view_zoom_to_window_xy_3d(region, step, zoom_xy);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
|
view3d_boxview_sync(area, region);
|
|
}
|
|
|
|
ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
|
|
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
|
|
|
|
ED_region_tag_redraw(region);
|
|
|
|
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
|
|
viewops_data_free(C, op->customdata);
|
|
op->customdata = NULL;
|
|
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
/* viewdolly_invoke() copied this function, changes here may apply there */
|
|
static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|
{
|
|
ViewOpsData *vod;
|
|
|
|
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
|
|
|
vod = op->customdata = viewops_data_create(
|
|
C,
|
|
event,
|
|
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
|
|
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
|
|
|
|
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
|
|
|
/* if one or the other zoom position aren't set, set from event */
|
|
if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
|
|
RNA_int_set(op->ptr, "mx", event->xy[0]);
|
|
RNA_int_set(op->ptr, "my", event->xy[1]);
|
|
}
|
|
|
|
if (RNA_struct_property_is_set(op->ptr, "delta")) {
|
|
viewzoom_exec(C, op);
|
|
}
|
|
else {
|
|
if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
|
|
|
|
if (U.uiflag & USER_ZOOM_HORIZ) {
|
|
vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
|
|
}
|
|
else {
|
|
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
|
|
vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->xy[0] -
|
|
event->prev_xy[0];
|
|
}
|
|
viewzoom_apply(vod,
|
|
event->prev_xy,
|
|
USER_ZOOM_DOLLY,
|
|
(U.uiflag & USER_ZOOM_INVERT) != 0,
|
|
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
|
|
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
|
|
|
viewops_data_free(C, op->customdata);
|
|
op->customdata = NULL;
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
if (U.viewzoom == USER_ZOOM_CONTINUE) {
|
|
/* needs a timer to continue redrawing */
|
|
vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
|
|
vod->prev.time = PIL_check_seconds_timer();
|
|
}
|
|
|
|
/* add temp handler */
|
|
WM_event_add_modal_handler(C, op);
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
}
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
static void viewzoom_cancel(bContext *C, wmOperator *op)
|
|
{
|
|
viewops_data_free(C, op->customdata);
|
|
op->customdata = NULL;
|
|
}
|
|
|
|
void VIEW3D_OT_zoom(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Zoom View";
|
|
ot->description = "Zoom in/out in the view";
|
|
ot->idname = "VIEW3D_OT_zoom";
|
|
|
|
/* api callbacks */
|
|
ot->invoke = viewzoom_invoke;
|
|
ot->exec = viewzoom_exec;
|
|
ot->modal = viewzoom_modal;
|
|
ot->poll = view3d_zoom_or_dolly_poll;
|
|
ot->cancel = viewzoom_cancel;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
|
|
|
|
/* properties */
|
|
view3d_operator_properties_common(
|
|
ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
|
|
}
|
|
|
|
/** \} */
|