Made 2D zoom consistent with 3D zoom for touchpads #110375
|
@ -559,7 +559,7 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
|
|||
static int lastdy = 0;
|
||||
const int dy = WM_event_absolute_delta_y(event);
|
||||
|
||||
/* This event should be originally from event->type,
|
||||
/* This event should originally be from event->type,
|
||||
* converting wrong event into wheel is bad, see #33803. */
|
||||
BLI_assert(*type == MOUSEPAN);
|
||||
|
||||
|
@ -6286,7 +6286,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
|
|||
hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f);
|
||||
}
|
||||
else {
|
||||
const float fac = 0.005 * (event->xy[1] - event->prev_xy[1]);
|
||||
const float fac = 0.005 / UI_SCALE_FAC * WM_event_absolute_delta_y(event);
|
||||
hsv[2] = clamp_f(hsv[2] + fac, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
|
|
|
@ -1317,7 +1317,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
|
|||
dx *= -1.0f;
|
||||
dy *= -1.0f;
|
||||
}
|
||||
|
||||
|
||||
/* set transform amount, and add current deltas to stored total delta (for redo) */
|
||||
RNA_float_set(op->ptr, "deltax", dx);
|
||||
RNA_float_set(op->ptr, "deltay", dy);
|
||||
|
|
|
@ -695,7 +695,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
}
|
||||
}
|
||||
else if (etype == MOUSEPAN) {
|
||||
float delta = 0.02f * (event->xy[1] - event->prev_xy[1]);
|
||||
float delta = 0.02f / UI_SCALE_FAC * WM_event_absolute_delta_y(event);
|
||||
if (opdata->segments >= 1 && opdata->segments + delta < 1) {
|
||||
opdata->segments = 1;
|
||||
}
|
||||
|
|
|
@ -595,13 +595,13 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
break;
|
||||
case MOUSEPAN:
|
||||
if ((event->modifier & KM_ALT) == 0) {
|
||||
cuts += 0.02f * (event->xy[1] - event->prev_xy[1]);
|
||||
cuts += 0.02f / UI_SCALE_FAC * WM_event_absolute_delta_y(event);
|
||||
if (cuts < 1 && lcd->cuts >= 1) {
|
||||
cuts = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
smoothness += 0.002f * (event->xy[1] - event->prev_xy[1]);
|
||||
smoothness += 0.002f / UI_SCALE_FAC * WM_event_absolute_delta_y(event);
|
||||
}
|
||||
handled = true;
|
||||
break;
|
||||
|
|
|
@ -605,13 +605,23 @@ static int view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
|
||||
float delta, factor;
|
||||
|
||||
delta = event->prev_xy[0] - event->xy[0] + event->prev_xy[1] - event->xy[1];
|
||||
|
||||
if (U.uiflag & USER_ZOOM_INVERT) {
|
||||
delta *= -1;
|
||||
if (event->type == MOUSEPAN) {
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
delta = WM_event_absolute_delta_x(event);
|
||||
}
|
||||
else {
|
||||
delta = WM_event_absolute_delta_y(event);
|
||||
}
|
||||
|
||||
if (U.uiflag & USER_ZOOM_INVERT) {
|
||||
delta *= -1;
|
||||
}
|
||||
}
|
||||
else { /* MOUSEZOOM */
|
||||
delta = WM_event_absolute_delta_x(event);
|
||||
}
|
||||
|
||||
factor = 1.0f + delta / 300.0f;
|
||||
factor = 1.0f + delta / UI_SCALE_FAC / 300.0f;
|
||||
RNA_float_set(op->ptr, "factor", factor);
|
||||
|
||||
sclip_zoom_set_factor_exec(C, event, factor);
|
||||
|
@ -642,7 +652,7 @@ static void view_zoom_apply(
|
|||
delta = event->xy[0] - vpd->x + event->xy[1] - vpd->y;
|
||||
}
|
||||
|
||||
delta /= U.pixelsize;
|
||||
delta /= U.pixelsize * UI_SCALE_FAC;
|
||||
|
||||
if (U.uiflag & USER_ZOOM_INVERT) {
|
||||
delta = -delta;
|
||||
|
|
|
@ -597,14 +597,24 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
|
|||
|
||||
UI_view2d_region_to_view(
|
||||
®ion->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
|
||||
|
||||
delta = event->prev_xy[0] - event->xy[0] + event->prev_xy[1] - event->xy[1];
|
||||
|
||||
if (U.uiflag & USER_ZOOM_INVERT) {
|
||||
delta *= -1;
|
||||
|
||||
if (event->type == MOUSEPAN) {
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
delta = WM_event_absolute_delta_x(event);
|
||||
}
|
||||
else {
|
||||
delta = WM_event_absolute_delta_y(event);
|
||||
}
|
||||
|
||||
if (U.uiflag & USER_ZOOM_INVERT) {
|
||||
delta *= -1;
|
||||
}
|
||||
}
|
||||
else { /* MOUSEZOOM */
|
||||
delta = WM_event_absolute_delta_x(event);
|
||||
}
|
||||
|
||||
factor = 1.0f + delta / 300.0f;
|
||||
factor = 1.0f + delta / UI_SCALE_FAC / 300.0f;
|
||||
RNA_float_set(op->ptr, "factor", factor);
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
sima_zoom_set(sima,
|
||||
|
@ -644,7 +654,7 @@ static void image_zoom_apply(ViewZoomData *vpd,
|
|||
delta = x - vpd->origx + y - vpd->origy;
|
||||
}
|
||||
|
||||
delta /= U.pixelsize;
|
||||
delta /= U.pixelsize * UI_SCALE_FAC;
|
||||
|
||||
if (zoom_invert) {
|
||||
delta = -delta;
|
||||
|
|
|
@ -335,8 +335,16 @@ void ViewOpsData::init_navigation(bContext *C,
|
|||
}
|
||||
|
||||
/* For dolly */
|
||||
const float mval[2] = {float(event->mval[0]), float(event->mval[1])};
|
||||
ED_view3d_win_to_vector(region, mval, this->init.mousevec);
|
||||
{
|
||||
float mval[2];
|
||||
if (viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) {
|
||||
copy_v2fl_v2i(mval, event->mval);
|
||||
}
|
||||
else {
|
||||
copy_v2_fl2(mval, (float)(region->winx / 2), (float)(region->winy / 2));
|
||||
}
|
||||
ED_view3d_win_to_vector(region, mval, this->init.mousevec);
|
||||
}
|
||||
|
||||
{
|
||||
int event_xy_offset[2];
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -155,10 +155,14 @@ struct ViewOpsData {
|
|||
|
||||
/** Current state. */
|
||||
struct {
|
||||
/** Working copy of #RegionView3D.viewquat, needed for rotation calculation
|
||||
* so we can apply snap to the 3D Viewport while keeping the unsnapped rotation
|
||||
* here to use when snap is disabled and for continued calculation. */
|
||||
float viewquat[4];
|
||||
union {
|
||||
/** Working copy of #RegionView3D.viewquat, needed for rotation calculation
|
||||
* so we can apply snap to the 3D Viewport while keeping the unsnapped rotation
|
||||
* here to use when snap is disabled and for continued calculation. */
|
||||
float viewquat[4];
|
||||
/** Total distance for continuous zoom */
|
||||
float total_dist;
|
||||
};
|
||||
} curr;
|
||||
|
||||
const ViewOpsType *nav_type;
|
||||
|
|
|
@ -472,6 +472,20 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
|
|||
else if (event->type == MOUSEMOVE) {
|
||||
copy_v2_v2_int(fly->mval, event->mval);
|
||||
}
|
||||
else if (event->type == MOUSEPAN) {
|
||||
float fac = -0.03f * WM_event_absolute_delta_y(event) / UI_SCALE_FAC;
|
||||
|
||||
/* allow to brake immediately */
|
||||
if (fac > 0.0f && fly->speed < 0.0f) {
|
||||
fly->speed = 0.0f;
|
||||
}
|
||||
else if (fac < 0.0f && fly->speed > 0.0f) {
|
||||
fly->speed = 0.0f;
|
||||
}
|
||||
else {
|
||||
fly->speed += fly->grid * fac;
|
||||
}
|
||||
}
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
else if (event->type == NDOF_MOTION) {
|
||||
/* do these automagically get delivered? yes. */
|
||||
|
@ -529,28 +543,9 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event)
|
|||
case FLY_MODAL_CONFIRM:
|
||||
fly->state = FLY_CONFIRM;
|
||||
break;
|
||||
|
||||
/* Speed adjusting with mouse-pan (track-pad). */
|
||||
case FLY_MODAL_SPEED: {
|
||||
float fac = 0.02f * (event->prev_xy[1] - event->xy[1]);
|
||||
|
||||
/* allowing to brake immediate */
|
||||
if (fac > 0.0f && fly->speed < 0.0f) {
|
||||
fly->speed = 0.0f;
|
||||
}
|
||||
else if (fac < 0.0f && fly->speed > 0.0f) {
|
||||
fly->speed = 0.0f;
|
||||
}
|
||||
else {
|
||||
fly->speed += fly->grid * fac;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case FLY_MODAL_ACCELERATE: {
|
||||
double time_currwheel;
|
||||
float time_wheel;
|
||||
|
||||
/* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
|
||||
if (fly->axis == -1) {
|
||||
fly->axis = 2;
|
||||
|
|
|
@ -72,35 +72,24 @@ static void view_dolly_to_vector_3d(ARegion *region,
|
|||
float dfac)
|
||||
{
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
|
||||
|
||||
madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -dfac);
|
||||
}
|
||||
|
||||
static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const bool zoom_invert)
|
||||
static void viewdolly_apply(ViewOpsData *vod, const int move_xy[2], const bool delta_invert)
|
||||
{
|
||||
float zfac = 1.0;
|
||||
float delta;
|
||||
const int sgn = 1 - 2 * delta_invert;
|
||||
|
||||
{
|
||||
float len1, len2;
|
||||
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
len1 = (vod->region->winrct.xmax - xy[0]) + 5;
|
||||
len2 = (vod->region->winrct.xmax - vod->init.event_xy[0]) + 5;
|
||||
}
|
||||
else {
|
||||
len1 = (vod->region->winrct.ymax - xy[1]) + 5;
|
||||
len2 = (vod->region->winrct.ymax - vod->init.event_xy[1]) + 5;
|
||||
}
|
||||
if (zoom_invert) {
|
||||
SWAP(float, len1, len2);
|
||||
}
|
||||
|
||||
zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist);
|
||||
}
|
||||
|
||||
if (zfac != 1.0f) {
|
||||
view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, zfac);
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
delta = float(sgn * move_xy[0]) / UI_SCALE_FAC * vod->init.dist / 130.0f;
|
||||
}
|
||||
else {
|
||||
delta = float(sgn * move_xy[1]) / UI_SCALE_FAC * vod->init.dist / 130.0f;
|
||||
}
|
||||
|
||||
view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, delta);
|
||||
|
||||
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(vod->area, vod->region);
|
||||
}
|
||||
|
@ -116,10 +105,14 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
short event_code = VIEW_PASS;
|
||||
bool use_autokey = false;
|
||||
int ret = OPERATOR_RUNNING_MODAL;
|
||||
int move_xy[2];
|
||||
|
||||
/* Execute the events. */
|
||||
if (event->type == EVT_MODAL_MAP) {
|
||||
switch (event->val) {
|
||||
case VIEW_MODAL_CANCEL:
|
||||
event_code = VIEW_CANCEL;
|
||||
break;
|
||||
case VIEW_MODAL_CONFIRM:
|
||||
event_code = VIEW_CONFIRM;
|
||||
break;
|
||||
|
@ -151,7 +144,9 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
switch (event_code) {
|
||||
case VIEW_APPLY: {
|
||||
viewdolly_apply(vod, event->xy, (U.uiflag & USER_ZOOM_INVERT) != 0);
|
||||
sub_v2_v2v2_int(move_xy, event->xy, vod->init.event_xy);
|
||||
viewdolly_apply(vod, move_xy, (U.uiflag & USER_ZOOM_INVERT) != 0);
|
||||
|
||||
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
||||
use_autokey = true;
|
||||
}
|
||||
|
@ -192,7 +187,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
|
|||
ARegion *region;
|
||||
float mousevec[3];
|
||||
|
||||
const int delta = RNA_int_get(op->ptr, "delta");
|
||||
float delta = float(RNA_int_get(op->ptr, "delta"));
|
||||
|
||||
if (op->customdata) {
|
||||
ViewOpsData *vod = static_cast<ViewOpsData *>(op->customdata);
|
||||
|
@ -200,32 +195,37 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
|
|||
area = vod->area;
|
||||
region = vod->region;
|
||||
copy_v3_v3(mousevec, vod->init.mousevec);
|
||||
delta *= vod->init.dist / 5.0f;
|
||||
}
|
||||
else {
|
||||
area = CTX_wm_area(C);
|
||||
region = CTX_wm_region(C);
|
||||
negate_v3_v3(mousevec, static_cast<RegionView3D *>(region->regiondata)->viewinv[2]);
|
||||
normalize_v3(mousevec);
|
||||
float reg_xy[2];
|
||||
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
if (use_cursor_init) {
|
||||
reg_xy[0] = float(RNA_int_get(op->ptr, "mx"));
|
||||
reg_xy[1] = float(RNA_int_get(op->ptr, "my"));
|
||||
}
|
||||
else {
|
||||
reg_xy[0] = float(region->winx / 2);
|
||||
reg_xy[1] = float(region->winy / 2);
|
||||
}
|
||||
ED_view3d_win_to_vector(region, reg_xy, mousevec);
|
||||
}
|
||||
|
||||
v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
|
||||
/* overwrite the mouse vector with the view direction (zoom into the center) */
|
||||
if ((use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
|
||||
normalize_v3_v3(mousevec, rv3d->viewinv[2]);
|
||||
negate_v3(mousevec);
|
||||
}
|
||||
|
||||
view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta < 0 ? 1.8f : 0.2f);
|
||||
view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta);
|
||||
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(area, region);
|
||||
}
|
||||
|
||||
ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
|
||||
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
|
||||
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
||||
|
@ -239,19 +239,17 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
|
|||
static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ViewOpsData *vod;
|
||||
|
||||
|
||||
if (viewdolly_offset_lock_check(C, op)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
|
||||
/* use_cursor_init is true by default */
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
|
||||
vod = viewops_data_create(C, event, &ViewOpsType_dolly, use_cursor_init);
|
||||
op->customdata = vod;
|
||||
|
||||
|
||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
||||
|
||||
/* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
|
||||
/* switch from camera view when: */
|
||||
if (vod->rv3d->persp != RV3D_PERSP) {
|
||||
if (vod->rv3d->persp == RV3D_CAMOB) {
|
||||
|
@ -265,45 +263,56 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
ED_region_tag_redraw(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 (!use_cursor_init) {
|
||||
RNA_int_set(op->ptr, "mx", vod->region->winx / 2);
|
||||
RNA_int_set(op->ptr, "my", vod->region->winy / 2);
|
||||
}
|
||||
else {
|
||||
/* if one or the other zoom direction is not set */
|
||||
if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
|
||||
RNA_int_set(op->ptr, "mx", event->mval[0]);
|
||||
RNA_int_set(op->ptr, "my", event->mval[1]);
|
||||
}
|
||||
else {
|
||||
const float reg_xy[2] = {float(RNA_int_get(op->ptr, "mx")), float(RNA_int_get(op->ptr, "my"))};
|
||||
/* recompute movement direction for dolly */
|
||||
ED_view3d_win_to_vector(vod->region, reg_xy, vod->init.mousevec);
|
||||
}
|
||||
}
|
||||
|
||||
if (RNA_struct_property_is_set(op->ptr, "delta")) {
|
||||
viewdolly_exec(C, op);
|
||||
return viewdolly_exec(C, op);
|
||||
}
|
||||
else {
|
||||
/* overwrite the mouse vector with the view direction (zoom into the center) */
|
||||
if ((use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
|
||||
negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
|
||||
normalize_v3(vod->init.mousevec);
|
||||
|
||||
/* do not set the delta property, as an integer it would be 0 here */
|
||||
if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
|
||||
int move_xy[2];
|
||||
bool zoominv;
|
||||
|
||||
if (event->type == MOUSEPAN) {
|
||||
move_xy[0] = WM_event_absolute_delta_x(event);
|
||||
move_xy[1] = WM_event_absolute_delta_y(event);
|
||||
zoominv = (U.uiflag & USER_ZOOM_INVERT) != 0;
|
||||
}
|
||||
|
||||
if (event->type == MOUSEZOOM) {
|
||||
/* Bypass Zoom invert flag for track pads (pass false always) */
|
||||
|
||||
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];
|
||||
}
|
||||
viewdolly_apply(vod, event->prev_xy, (U.uiflag & USER_ZOOM_INVERT) == 0);
|
||||
|
||||
viewops_data_free(C, static_cast<ViewOpsData *>(op->customdata));
|
||||
op->customdata = nullptr;
|
||||
return OPERATOR_FINISHED;
|
||||
else { /* MOUSEZOOM */
|
||||
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
|
||||
move_xy[1] = move_xy[0] = WM_event_absolute_delta_x(event);
|
||||
zoominv = false;
|
||||
}
|
||||
|
||||
/* add temp handler */
|
||||
WM_event_add_modal_handler(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
|
||||
viewdolly_apply(vod, move_xy, zoominv);
|
||||
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
||||
|
||||
viewops_data_free(C, static_cast<ViewOpsData *>(op->customdata));
|
||||
op->customdata = nullptr;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
return OPERATOR_FINISHED;
|
||||
|
||||
/* add temp handler */
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
void VIEW3D_OT_dolly(wmOperatorType *ot)
|
||||
|
@ -317,11 +326,11 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
|
|||
ot->invoke = viewdolly_invoke;
|
||||
ot->exec = viewdolly_exec;
|
||||
ot->modal = viewdolly_modal;
|
||||
ot->poll = view3d_rotation_poll;
|
||||
ot->poll = view3d_zoom_or_dolly_poll;
|
||||
ot->cancel = view3d_navigate_cancel_fn;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY | OPTYPE_DEPENDS_ON_CURSOR;
|
||||
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
|
||||
|
||||
/* properties */
|
||||
view3d_operator_properties_common(
|
||||
|
|
|
@ -0,0 +1,359 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spview3d
|
||||
*/
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "ED_screen.hh"
|
||||
|
||||
#include "view3d_intern.h"
|
||||
#include "view3d_navigate.hh" /* own include */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name View Dolly Operator
|
||||
*
|
||||
* Like zoom but translates the view offset along the view direction
|
||||
* which avoids #RegionView3D.dist approaching zero.
|
||||
* \{ */
|
||||
|
||||
/* This is an exact copy of #viewzoom_modal_keymap. */
|
||||
void viewdolly_modal_keymap(wmKeyConfig *keyconf)
|
||||
{
|
||||
static const EnumPropertyItem modal_items[] = {
|
||||
{VIEW_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
|
||||
{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, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Dolly 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 Dolly Modal", modal_items);
|
||||
|
||||
/* assign map to operators */
|
||||
WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
|
||||
}
|
||||
|
||||
static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
|
||||
{
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
if (ED_view3d_offset_lock_check(v3d, rv3d)) {
|
||||
BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void view_dolly_to_vector_3d(ARegion *region,
|
||||
const float orig_ofs[3],
|
||||
const float dvec[3],
|
||||
float dfac)
|
||||
{
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -dfac);
|
||||
}
|
||||
|
||||
static void viewdolly_apply(ViewOpsData *vod, const int move_xy[2], const bool delta_invert)
|
||||
{
|
||||
float delta;
|
||||
const int sgn = 1 - 2 * delta_invert;
|
||||
|
||||
/* the factor 1.2 adjusts the input sensitivity */
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
delta = 1.2f * (float)(sgn * move_xy[0]) / vod->region->winx * vod->rv3d->dist;
|
||||
}
|
||||
else {
|
||||
delta = 1.2f * (float)(sgn * move_xy[1]) / vod->region->winy * vod->rv3d->dist;
|
||||
}
|
||||
|
||||
view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, delta);
|
||||
|
||||
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 int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ViewOpsData *vod = static_cast<ViewOpsData *>(op->customdata);
|
||||
short event_code = VIEW_PASS;
|
||||
bool use_autokey = false;
|
||||
int ret = OPERATOR_RUNNING_MODAL;
|
||||
int move_xy[2];
|
||||
|
||||
/* Execute the events. */
|
||||
if (event->type == EVT_MODAL_MAP) {
|
||||
switch (event->val) {
|
||||
case VIEW_MODAL_CANCEL:
|
||||
event_code = VIEW_CANCEL;
|
||||
break;
|
||||
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, nullptr, event);
|
||||
event_code = VIEW_CONFIRM;
|
||||
break;
|
||||
case VIEWROT_MODAL_SWITCH_ROTATE:
|
||||
WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, nullptr, event);
|
||||
event_code = VIEW_CONFIRM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event->type == MOUSEMOVE) {
|
||||
event_code = VIEW_APPLY;
|
||||
}
|
||||
else if (event->type == vod->init.event_type) {
|
||||
if (event->val == KM_RELEASE) {
|
||||
event_code = VIEW_CONFIRM;
|
||||
}
|
||||
}
|
||||
else if (event->type == EVT_ESCKEY) {
|
||||
if (event->val == KM_PRESS) {
|
||||
event_code = VIEW_CANCEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (event_code) {
|
||||
case VIEW_APPLY: {
|
||||
sub_v2_v2v2_int(move_xy, event->xy, vod->init.event_xy);
|
||||
viewdolly_apply(vod, move_xy, (U.uiflag & USER_ZOOM_INVERT) != 0);
|
||||
|
||||
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: {
|
||||
vod->state_restore();
|
||||
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, vod);
|
||||
op->customdata = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int viewdolly_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
View3D *v3d;
|
||||
RegionView3D *rv3d;
|
||||
ScrArea *area;
|
||||
ARegion *region;
|
||||
float mousevec[3];
|
||||
|
||||
const int delta = RNA_int_get(op->ptr, "delta");
|
||||
|
||||
if (op->customdata) {
|
||||
ViewOpsData *vod = static_cast<ViewOpsData *>(op->customdata);
|
||||
|
||||
area = vod->area;
|
||||
region = vod->region;
|
||||
copy_v3_v3(mousevec, vod->init.mousevec);
|
||||
}
|
||||
else {
|
||||
area = CTX_wm_area(C);
|
||||
region = CTX_wm_region(C);
|
||||
float xy[2];
|
||||
|
||||
/* compute direction vector for given zoom direction */
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
if (use_cursor_init) {
|
||||
xy[0] = (float)RNA_int_get(op->ptr, "mx");
|
||||
xy[1] = (float)RNA_int_get(op->ptr, "my");
|
||||
}
|
||||
else {
|
||||
xy[0] = (float)region->winx / 2.0f;
|
||||
xy[1] = (float)region->winy / 2.0f;
|
||||
}
|
||||
ED_view3d_win_to_vector(region, xy, mousevec);
|
||||
}
|
||||
|
||||
v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta);
|
||||
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(area, region);
|
||||
}
|
||||
|
||||
ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
|
||||
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
|
||||
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
||||
viewops_data_free(C, static_cast<ViewOpsData *>(op->customdata));
|
||||
op->customdata = nullptr;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/* copied from viewzoom_invoke(), changes here may apply there */
|
||||
static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ViewOpsData *vod;
|
||||
|
||||
if (viewdolly_offset_lock_check(C, op)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* use_cursor_init is true by default */
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
<<<<<<< HEAD:source/blender/editors/space_view3d/view3d_navigate_dolly.cc
|
||||
vod = viewops_data_create(C, event, V3D_OP_MODE_DOLLY, use_cursor_init);
|
||||
=======
|
||||
|
||||
vod = viewops_data_create(C, event, &ViewOpsType_dolly, use_cursor_init);
|
||||
>>>>>>> main:source/blender/editors/space_view3d/view3d_navigate_view_dolly.cc
|
||||
op->customdata = vod;
|
||||
|
||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
||||
|
||||
/* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
|
||||
/* switch from camera view when: */
|
||||
if (vod->rv3d->persp != RV3D_PERSP) {
|
||||
if (vod->rv3d->persp == RV3D_CAMOB) {
|
||||
/* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
|
||||
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP);
|
||||
}
|
||||
else {
|
||||
vod->rv3d->persp = RV3D_PERSP;
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(vod->region);
|
||||
}
|
||||
|
||||
/* if one or the other zoom direction is not set */
|
||||
if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
|
||||
/* set xy to region local coordinates */
|
||||
int xy[2];
|
||||
|
||||
if (use_cursor_init) {
|
||||
xy[0] = event->mval[0];
|
||||
xy[1] = event->mval[1];
|
||||
}
|
||||
else {
|
||||
xy[0] = vod->region->winx / 2;
|
||||
xy[1] = vod->region->winy / 2;
|
||||
}
|
||||
|
||||
RNA_int_set(op->ptr, "mx", xy[0]);
|
||||
RNA_int_set(op->ptr, "my", xy[1]);
|
||||
}
|
||||
else {
|
||||
/* recompute direction vector for given zoom direction */
|
||||
const float xy[2] = {(float)RNA_int_get(op->ptr, "mx"),
|
||||
(float)RNA_int_get(op->ptr, "my")};
|
||||
ED_view3d_win_to_vector(vod->region, xy, vod->init.mousevec);
|
||||
}
|
||||
|
||||
if (RNA_struct_property_is_set(op->ptr, "delta")) {
|
||||
return viewdolly_exec(C, op);
|
||||
}
|
||||
else {
|
||||
/* we do not set the delta property. It is an int, so usually would be
|
||||
* 0 if rounded from a float */
|
||||
if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
|
||||
int move_xy[2];
|
||||
sub_v2_v2v2_int(move_xy, event->prev_xy, event->xy);
|
||||
if (event->type == MOUSEZOOM) {
|
||||
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
|
||||
move_xy[1] = move_xy[0];
|
||||
}
|
||||
|
||||
viewdolly_apply(vod, move_xy, ((U.uiflag & USER_ZOOM_INVERT) != 0)
|
||||
^ ((event->flag & WM_EVENT_SCROLL_INVERT) !=0));
|
||||
|
||||
viewops_data_free(C, static_cast<ViewOpsData *>(op->customdata));
|
||||
op->customdata = nullptr;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/* add temp handler */
|
||||
WM_event_add_modal_handler(C, op);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
}
|
||||
|
||||
void VIEW3D_OT_dolly(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Dolly View";
|
||||
ot->description = "Dolly in/out in the view";
|
||||
ot->idname = ViewOpsType_dolly.idname;
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = viewdolly_invoke;
|
||||
ot->exec = viewdolly_exec;
|
||||
ot->modal = viewdolly_modal;
|
||||
ot->poll = view3d_zoom_or_dolly_poll;
|
||||
ot->cancel = view3d_navigate_cancel_fn;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
ViewOpsType ViewOpsType_dolly = {
|
||||
/*flag*/ (VIEWOPS_FLAG_DEPTH_NAVIGATE | VIEWOPS_FLAG_ZOOM_TO_MOUSE),
|
||||
/*idname*/ "VIEW3D_OT_dolly",
|
||||
/*poll_fn*/ nullptr,
|
||||
/*init_fn*/ nullptr,
|
||||
/*apply_fn*/ nullptr,
|
||||
};
|
|
@ -344,19 +344,18 @@ static int viewrotate_invoke_impl(bContext * /*C*/,
|
|||
eV3D_OpEvent event_code = ELEM(event->type, MOUSEROTATE, MOUSEPAN) ? VIEW_CONFIRM : VIEW_PASS;
|
||||
|
||||
if (event_code == VIEW_CONFIRM) {
|
||||
/* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
|
||||
const bool is_inverted = (event->flag & WM_EVENT_SCROLL_INVERT) &&
|
||||
(event->type != MOUSEROTATE);
|
||||
|
||||
int m_xy[2];
|
||||
if (is_inverted) {
|
||||
m_xy[0] = 2 * event->xy[0] - event->prev_xy[0];
|
||||
m_xy[1] = 2 * event->xy[1] - event->prev_xy[1];
|
||||
|
||||
if (event->type == MOUSEPAN) {
|
||||
m_xy[0] = event->xy[0] + WM_event_absolute_delta_x(event);
|
||||
m_xy[1] = event->xy[1] + WM_event_absolute_delta_y(event);
|
||||
}
|
||||
else {
|
||||
/* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
|
||||
copy_v2_v2_int(m_xy, event->prev_xy);
|
||||
}
|
||||
viewrotate_apply(vod, m_xy);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,296 +57,112 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
|
|||
|
||||
/**
|
||||
* \param zoom_xy: Optionally zoom to window location
|
||||
* (coords compatible w/ #wmEvent.xy). Use when not nullptr.
|
||||
* (coords compatible w/ #wmEvent.mval).
|
||||
*/
|
||||
static void view_zoom_to_window_xy_camera(Scene *scene,
|
||||
Depsgraph *depsgraph,
|
||||
View3D *v3d,
|
||||
ARegion *region,
|
||||
float dfac,
|
||||
const int zoom_xy[2])
|
||||
static void view_zoom_to_vector_3d(const View3D *v3d,
|
||||
ARegion *region,
|
||||
const float orig_ofs[3],
|
||||
const float orig_dist,
|
||||
const float orig_mval[2],
|
||||
float delta)
|
||||
{
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(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 != nullptr) {
|
||||
float zoomfac_px;
|
||||
rctf camera_frame_old;
|
||||
rctf camera_frame_new;
|
||||
|
||||
const float pt_src[2] = {float(zoom_xy[0]), float(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 nullptr.
|
||||
*/
|
||||
static void view_zoom_to_window_xy_3d(ARegion *region, float dfac, const int zoom_xy[2])
|
||||
{
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
const float dist_new = rv3d->dist * dfac;
|
||||
|
||||
if (zoom_xy != nullptr) {
|
||||
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 /= UI_SCALE_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 * UI_SCALE_FAC) + (float(len_v2v2_int(ctr, xy_curr)) / UI_SCALE_FAC);
|
||||
float len_old = (5 * UI_SCALE_FAC) + (float(len_v2v2_int(ctr, xy_init)) / UI_SCALE_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 * UI_SCALE_FAC;
|
||||
float len_old = 5 * UI_SCALE_FAC;
|
||||
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
len_new += (winrct->xmax - (xy_curr[0])) / UI_SCALE_FAC;
|
||||
len_old += (winrct->xmax - (xy_init[0])) / UI_SCALE_FAC;
|
||||
}
|
||||
else {
|
||||
len_new += (winrct->ymax - (xy_curr[1])) / UI_SCALE_FAC;
|
||||
len_old += (winrct->ymax - (xy_init[1])) / UI_SCALE_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 : nullptr);
|
||||
}
|
||||
|
||||
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 : nullptr);
|
||||
float ctr_xy[2];
|
||||
float v[3];
|
||||
|
||||
ED_view3d_dist_range_get(v3d, dist_range);
|
||||
rv3d->dist = orig_dist - delta;
|
||||
CLAMP(rv3d->dist, dist_range[0], dist_range[1]);
|
||||
|
||||
ctr_xy[0] = orig_mval[0] - region->winx / 2;
|
||||
ctr_xy[1] = orig_mval[1] - region->winy / 2;
|
||||
|
||||
if (rv3d->persp != RV3D_ORTHO) {
|
||||
ED_view3d_win_to_delta(region, ctr_xy, -delta, v);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
else {
|
||||
ED_view3d_win_to_delta(region, ctr_xy, -delta/rv3d->dist, v);
|
||||
}
|
||||
add_v3_v3v3(rv3d->ofs, orig_ofs, v);
|
||||
}
|
||||
|
||||
static void viewzoom_apply(ViewOpsData *vod, const int move_xy[2],
|
||||
const eViewZoom_Style zoomstyle, const bool delta_invert, const int zoomctr_xy[2])
|
||||
{
|
||||
const int sgn = 1 - 2 * delta_invert;
|
||||
|
||||
if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
|
||||
float scale;
|
||||
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
scale = 1.0f + float(sgn * move_xy[0]) / UI_SCALE_FAC / 300.0f;
|
||||
}
|
||||
else {
|
||||
scale = 1.0f + float(sgn * move_xy[1]) / UI_SCALE_FAC / 300.0f;
|
||||
}
|
||||
ED_view3d_camera_view_zoom_scale(vod->rv3d, scale);
|
||||
}
|
||||
else {
|
||||
float delta;
|
||||
|
||||
if (zoomstyle == USER_ZOOM_CONTINUE) {
|
||||
double time = PIL_check_seconds_timer();
|
||||
float move_t = float(time - vod->prev.time);
|
||||
vod->prev.time = time;
|
||||
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
delta = float(sgn * move_xy[0]) / UI_SCALE_FAC / 130.0f;
|
||||
}
|
||||
else {
|
||||
delta = float(sgn * move_xy[1]) / UI_SCALE_FAC / 130.0f;
|
||||
}
|
||||
delta *= move_t * vod->init.dist;
|
||||
delta = vod->curr.total_dist += delta;
|
||||
}
|
||||
else if (zoomstyle == USER_ZOOM_SCALE) {
|
||||
/* method which zooms based on how far you move the mouse */
|
||||
float delta_xy[2];
|
||||
float radii[2];
|
||||
int ctr_xy[2];
|
||||
|
||||
ctr_xy[0] = BLI_rcti_cent_x(&vod->region->winrct);
|
||||
ctr_xy[1] = BLI_rcti_cent_y(&vod->region->winrct);
|
||||
|
||||
/* initial radius */
|
||||
radii[0] = max_ff(len_v2v2_int(vod->init.event_xy, ctr_xy), 1.0f);
|
||||
|
||||
delta_xy[0] = float(vod->init.event_xy[0] - ctr_xy[0] + move_xy[0]);
|
||||
delta_xy[1] = float(vod->init.event_xy[1] - ctr_xy[1] + move_xy[1]);
|
||||
/* current radius */
|
||||
radii[1] = max_ff(len_v2(delta_xy), 1.0f);
|
||||
|
||||
delta = (radii[1] / radii[0] - 1.0f) * vod->init.dist * 2.0f;
|
||||
}
|
||||
else { /* USER_ZOOM_DOLLY */
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
delta = float(sgn * move_xy[0]) / UI_SCALE_FAC * vod->init.dist / 130.0f;
|
||||
}
|
||||
else {
|
||||
delta = float(sgn * move_xy[1]) / UI_SCALE_FAC * vod->init.dist / 130.0f;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const float zoomctr_f_xy[2] = {float(zoomctr_xy[0]), float(zoomctr_xy[1])};
|
||||
view_zoom_to_vector_3d(vod->v3d, vod->region, vod->init.ofs, vod->init.dist, zoomctr_f_xy, delta);
|
||||
}
|
||||
|
||||
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 = (vod->viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) != 0;
|
||||
|
||||
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_impl(bContext *C,
|
||||
ViewOpsData *vod,
|
||||
const eV3D_OpEvent event_code,
|
||||
|
@ -354,10 +170,22 @@ static int viewzoom_modal_impl(bContext *C,
|
|||
{
|
||||
bool use_autokey = false;
|
||||
int ret = OPERATOR_RUNNING_MODAL;
|
||||
int move_xy[2];
|
||||
int zoomctr_xy[2];
|
||||
|
||||
switch (event_code) {
|
||||
case VIEW_APPLY: {
|
||||
viewzoom_apply(vod, xy, (eViewZoom_Style)U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0);
|
||||
if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
|
||||
sub_v2_v2v2_int(move_xy, xy, vod->prev.event_xy);
|
||||
copy_v2_v2_int(vod->prev.event_xy, xy);
|
||||
}
|
||||
else {
|
||||
sub_v2_v2v2_int(move_xy, xy, vod->init.event_xy);
|
||||
copy_v2_v2_int(zoomctr_xy, vod->init.event_xy_offset);
|
||||
}
|
||||
viewzoom_apply(vod, move_xy, (eViewZoom_Style)U.viewzoom,
|
||||
(U.uiflag & USER_ZOOM_INVERT) != 0, zoomctr_xy);
|
||||
|
||||
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
|
||||
use_autokey = true;
|
||||
}
|
||||
|
@ -384,84 +212,78 @@ static int viewzoom_modal_impl(bContext *C,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void view_zoom_apply_step(bContext *C,
|
||||
Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
ScrArea *area,
|
||||
ARegion *region,
|
||||
const int delta,
|
||||
const int zoom_xy[2])
|
||||
static int viewzoom_apply_step(bContext *C, PointerRNA *ptr, ViewOpsData *vod, const int zoomctr_xy[2])
|
||||
{
|
||||
View3D *v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
bool use_cam_zoom;
|
||||
float dist_range[2];
|
||||
View3D *v3d;
|
||||
RegionView3D *rv3d;
|
||||
ScrArea *area;
|
||||
ARegion *region;
|
||||
|
||||
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
|
||||
!(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
|
||||
const int delta = RNA_int_get(ptr, "delta");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
/* execution is always based on input device event */
|
||||
area = vod->area;
|
||||
region = vod->region;
|
||||
v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
if ((rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(v3d, rv3d)) {
|
||||
const float scale = 1.0f + 0.1f * delta;
|
||||
ED_view3d_camera_view_zoom_scale(rv3d, scale);
|
||||
}
|
||||
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);
|
||||
}
|
||||
const float zoomctr_f_xy[2] = {float(zoomctr_xy[0]), float(zoomctr_xy[1])};
|
||||
view_zoom_to_vector_3d(v3d, region, rv3d->ofs, rv3d->dist, zoomctr_f_xy, delta * vod->init.dist / 5.0f);
|
||||
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(area, region);
|
||||
}
|
||||
}
|
||||
|
||||
ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
|
||||
ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true);
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int viewzoom_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
View3D *v3d;
|
||||
RegionView3D *rv3d;
|
||||
ScrArea *area;
|
||||
ARegion *region;
|
||||
|
||||
const int delta = RNA_int_get(op->ptr, "delta");
|
||||
|
||||
area = CTX_wm_area(C);
|
||||
region = CTX_wm_region(C);
|
||||
float zoomctr_f_xy[2];
|
||||
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
if (use_cursor_init) {
|
||||
zoomctr_f_xy[0] = float(RNA_int_get(op->ptr, "mx"));
|
||||
zoomctr_f_xy[1] = float(RNA_int_get(op->ptr, "my"));
|
||||
}
|
||||
else {
|
||||
zoomctr_f_xy[0] = float(region->winx / 2);
|
||||
zoomctr_f_xy[1] = float(region->winy / 2);
|
||||
}
|
||||
|
||||
v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
view_zoom_to_vector_3d(v3d, region, rv3d->ofs, rv3d->dist, zoomctr_f_xy, delta);
|
||||
|
||||
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_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
|
||||
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
}
|
||||
|
||||
static int viewzoom_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
BLI_assert(op->customdata == nullptr);
|
||||
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
View3D *v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
const int delta = RNA_int_get(op->ptr, "delta");
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
|
||||
int zoom_xy_buf[2];
|
||||
const int *zoom_xy = nullptr;
|
||||
const bool do_zoom_to_mouse_pos = (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS));
|
||||
if (do_zoom_to_mouse_pos) {
|
||||
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;
|
||||
}
|
||||
|
||||
view_zoom_apply_step(C, depsgraph, scene, area, region, delta, zoom_xy);
|
||||
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
@ -471,53 +293,71 @@ static int viewzoom_invoke_impl(bContext *C,
|
|||
const wmEvent *event,
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
int xy[2];
|
||||
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_struct_find_property(ptr, "mx");
|
||||
xy[0] = RNA_property_is_set(ptr, prop) ? RNA_property_int_get(ptr, prop) : event->xy[0];
|
||||
|
||||
prop = RNA_struct_find_property(ptr, "my");
|
||||
xy[1] = RNA_property_is_set(ptr, prop) ? RNA_property_int_get(ptr, prop) : event->xy[1];
|
||||
|
||||
prop = RNA_struct_find_property(ptr, "delta");
|
||||
const int delta = RNA_property_is_set(ptr, prop) ? RNA_property_int_get(ptr, prop) : 0;
|
||||
|
||||
if (delta) {
|
||||
const bool do_zoom_to_mouse_pos = (vod->viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) != 0;
|
||||
view_zoom_apply_step(C,
|
||||
vod->depsgraph,
|
||||
vod->scene,
|
||||
vod->area,
|
||||
vod->region,
|
||||
delta,
|
||||
do_zoom_to_mouse_pos ? xy : nullptr);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
int zoomctr_xy[2];
|
||||
|
||||
/* use_cursor_init is true by default */
|
||||
const bool use_cursor_init = RNA_boolean_get(ptr, "use_cursor_init");
|
||||
|
||||
if (!use_cursor_init) {
|
||||
RNA_int_set(ptr, "mx", zoomctr_xy[0] = vod->region->winx / 2);
|
||||
RNA_int_set(ptr, "my", zoomctr_xy[1] = vod->region->winy / 2);
|
||||
}
|
||||
else {
|
||||
eV3D_OpEvent event_code = ELEM(event->type, MOUSEZOOM, MOUSEPAN) ? VIEW_CONFIRM : VIEW_PASS;
|
||||
if (event_code == VIEW_CONFIRM) {
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
vod->init.event_xy[0] = vod->prev.event_xy[0] = xy[0];
|
||||
/* if one or the other zoom direction is not set */
|
||||
if (!RNA_struct_property_is_set(ptr, "mx") || !RNA_struct_property_is_set(ptr, "my")) {
|
||||
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
|
||||
copy_v2_v2_int(zoomctr_xy, event->mval);
|
||||
}
|
||||
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] + xy[0] -
|
||||
event->prev_xy[0];
|
||||
zoomctr_xy[0] = vod->region->winx / 2;
|
||||
zoomctr_xy[1] = vod->region->winy / 2;
|
||||
}
|
||||
viewzoom_apply(vod, event->prev_xy, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
|
||||
RNA_int_set(ptr, "mx", zoomctr_xy[0]);
|
||||
RNA_int_set(ptr, "my", zoomctr_xy[1]);
|
||||
}
|
||||
else {
|
||||
zoomctr_xy[0] = RNA_int_get(ptr, "mx");
|
||||
zoomctr_xy[1] = RNA_int_get(ptr, "my");
|
||||
}
|
||||
}
|
||||
|
||||
if (RNA_struct_property_is_set(ptr, "delta")) {
|
||||
return viewzoom_apply_step(C, ptr, vod, zoomctr_xy);
|
||||
}
|
||||
else {
|
||||
/* do not set the delta property, as an integer it would be 0 here */
|
||||
if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
|
||||
int move_xy[2];
|
||||
bool zoominv;
|
||||
|
||||
if (event->type == MOUSEPAN) {
|
||||
move_xy[0] = WM_event_absolute_delta_x(event);
|
||||
move_xy[1] = WM_event_absolute_delta_y(event);
|
||||
|
||||
zoominv = (U.uiflag & USER_ZOOM_INVERT) != 0;
|
||||
}
|
||||
else { /* MOUSEZOOM */
|
||||
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
|
||||
move_xy[1] = move_xy[0] = WM_event_absolute_delta_x(event);
|
||||
zoominv = false;
|
||||
}
|
||||
|
||||
viewzoom_apply(vod, move_xy, USER_ZOOM_DOLLY, zoominv, zoomctr_xy);
|
||||
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
||||
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
if (U.viewzoom == USER_ZOOM_CONTINUE) {
|
||||
/* needs a timer to continue redrawing */
|
||||
vod->timer = WM_event_timer_add(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
|
||||
vod->prev.time = PIL_check_seconds_timer();
|
||||
vod->timer = WM_event_timer_add(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
|
||||
}
|
||||
|
||||
copy_v2_v2_int(vod->init.event_xy_offset, zoomctr_xy);
|
||||
copy_v2_v2_int(vod->prev.event_xy, event->xy);
|
||||
vod->curr.total_dist = 0.0f;
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,414 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* 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.hh"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "ED_screen.hh"
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
||||
#include "view3d_intern.h"
|
||||
#include "view3d_navigate.hh" /* 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_CANCEL, "CANCEL", 0, "Cancel", ""},
|
||||
{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, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
/* assign map to operators */
|
||||
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
|
||||
}
|
||||
|
||||
/**
|
||||
* \param zoom_xy: Optionally zoom to window location
|
||||
* (coords compatible w/ #wmEvent.mval).
|
||||
*/
|
||||
static void view_zoom_to_window_xy_3d(const View3D *v3d,
|
||||
ARegion *region,
|
||||
const float orig_ofs[3],
|
||||
const float orig_dist,
|
||||
const float orig_mval[2],
|
||||
float delta)
|
||||
{
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
float dist_range[2];
|
||||
float cent_xy[2];
|
||||
float v[3];
|
||||
|
||||
ED_view3d_dist_range_get(v3d, dist_range);
|
||||
rv3d->dist = orig_dist - delta;
|
||||
CLAMP(rv3d->dist, dist_range[0], dist_range[1]);
|
||||
|
||||
cent_xy[0] = orig_mval[0] - region->winx / 2;
|
||||
cent_xy[1] = orig_mval[1] - region->winy / 2;
|
||||
|
||||
if (rv3d->persp != RV3D_ORTHO) {
|
||||
ED_view3d_win_to_delta(region, cent_xy, -delta, v);
|
||||
}
|
||||
else {
|
||||
ED_view3d_win_to_delta(region, cent_xy, -delta/rv3d->dist, v);
|
||||
}
|
||||
add_v3_v3v3(rv3d->ofs, orig_ofs, v);
|
||||
}
|
||||
|
||||
static void viewzoom_apply(ViewOpsData *vod, const int move_xy[2],
|
||||
const eViewZoom_Style zoomstyle, const bool delta_invert, const float mval[2])
|
||||
{
|
||||
const int sgn = 1 - 2 * delta_invert;
|
||||
|
||||
if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
|
||||
float scale;
|
||||
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
scale = 1.0f + (float)(sgn * move_xy[0]) / vod->region->winx;
|
||||
}
|
||||
else {
|
||||
scale = 1.0f + (float)(sgn * move_xy[1]) / vod->region->winy;
|
||||
}
|
||||
ED_view3d_camera_view_zoom_scale(vod->rv3d, scale);
|
||||
}
|
||||
else {
|
||||
float delta;
|
||||
|
||||
if (zoomstyle == USER_ZOOM_CONTINUE) {
|
||||
double time = PIL_check_seconds_timer();
|
||||
float move_t = (float)(time - vod->prev.time);
|
||||
vod->prev.time = time;
|
||||
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
delta = 1.2f * (float)(sgn * move_xy[0]) / vod->region->winx;
|
||||
}
|
||||
else {
|
||||
delta = 1.2f * (float)(sgn * move_xy[1]) / vod->region->winy;
|
||||
}
|
||||
delta *= move_t * vod->rv3d->dist;
|
||||
delta = vod->init.zfac += delta;
|
||||
}
|
||||
else if (zoomstyle == USER_ZOOM_SCALE) {
|
||||
/* method which zooms based on how far you move the mouse */
|
||||
float delta_xy[2];
|
||||
float radii[2];
|
||||
int c_xy[2];
|
||||
|
||||
c_xy[0] = BLI_rcti_cent_x(&vod->region->winrct);
|
||||
c_xy[1] = BLI_rcti_cent_y(&vod->region->winrct);
|
||||
/* initial radius */
|
||||
radii[0] = max_ff(len_v2v2_int(vod->init.event_xy, c_xy) / vod->region->winx, 0.05f);
|
||||
|
||||
delta_xy[0] = (float)(vod->init.event_xy[0] + move_xy[0] - c_xy[0]);
|
||||
delta_xy[1] = (float)(vod->init.event_xy[1] + move_xy[1] - c_xy[1]);
|
||||
/* current radius */
|
||||
radii[1] = max_ff(len_v2(delta_xy) / vod->region->winx, 0.05f);
|
||||
|
||||
delta = 1.2f * (radii[1] / radii[0] - 1.0f) * vod->rv3d->dist;
|
||||
}
|
||||
else { /* USER_ZOOM_DOLLY */
|
||||
/* the factor 1.2 adjusts the input sensitivity */
|
||||
if (U.uiflag & USER_ZOOM_HORIZ) {
|
||||
delta = 1.2f * (float)(sgn * move_xy[0]) / vod->region->winx * vod->rv3d->dist;
|
||||
}
|
||||
else {
|
||||
delta = 1.2f * (float)(sgn * move_xy[1]) / vod->region->winy * vod->rv3d->dist;
|
||||
}
|
||||
}
|
||||
|
||||
view_zoom_to_window_xy_3d(vod->v3d, vod->region, vod->init.ofs, vod->init.dist, mval, delta);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
<<<<<<< HEAD:source/blender/editors/space_view3d/view3d_navigate_zoom.cc
|
||||
int viewzoom_modal_impl(bContext *C,
|
||||
ViewOpsData *vod,
|
||||
const eV3D_OpEvent event_code,
|
||||
const int xy[2])
|
||||
=======
|
||||
static void viewzoom_apply(ViewOpsData *vod,
|
||||
const int xy[2],
|
||||
const eViewZoom_Style viewzoom,
|
||||
const bool zoom_invert)
|
||||
{
|
||||
const bool zoom_to_pos = (vod->viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) != 0;
|
||||
|
||||
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_impl(bContext *C,
|
||||
ViewOpsData *vod,
|
||||
const eV3D_OpEvent event_code,
|
||||
const int xy[2])
|
||||
>>>>>>> main:source/blender/editors/space_view3d/view3d_navigate_view_zoom.cc
|
||||
{
|
||||
bool use_autokey = false;
|
||||
int ret = OPERATOR_RUNNING_MODAL;
|
||||
int move_xy[2];
|
||||
float mval[2];
|
||||
|
||||
switch (event_code) {
|
||||
case VIEW_APPLY: {
|
||||
if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
|
||||
sub_v2_v2v2_int(move_xy, xy, vod->prev.event_xy);
|
||||
copy_v2_v2_int(vod->prev.event_xy, xy);
|
||||
}
|
||||
else {
|
||||
sub_v2_v2v2_int(move_xy, xy, vod->init.event_xy);
|
||||
mval[0] = vod->region->winx / 2.0f + vod->init.event_xy_offset[0];
|
||||
mval[1] = vod->region->winy / 2.0f + vod->init.event_xy_offset[1];
|
||||
}
|
||||
viewzoom_apply(vod, move_xy, (eViewZoom_Style)U.viewzoom,
|
||||
(U.uiflag & USER_ZOOM_INVERT) != 0, mval);
|
||||
|
||||
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: {
|
||||
vod->state_restore();
|
||||
ret = OPERATOR_CANCELLED;
|
||||
break;
|
||||
}
|
||||
case VIEW_PASS:
|
||||
break;
|
||||
}
|
||||
|
||||
if (use_autokey) {
|
||||
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int viewzoom_apply_step(bContext *C, PointerRNA *ptr, ViewOpsData *vod, const float mval[2])
|
||||
{
|
||||
View3D *v3d;
|
||||
RegionView3D *rv3d;
|
||||
ScrArea *area;
|
||||
ARegion *region;
|
||||
|
||||
const int delta = RNA_int_get(ptr, "delta");
|
||||
|
||||
/* based on input device event */
|
||||
area = vod->area;
|
||||
region = vod->region;
|
||||
v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
if ((rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(v3d, rv3d)) {
|
||||
float scale;
|
||||
|
||||
scale = 1.0f + 0.1f * delta;
|
||||
ED_view3d_camera_view_zoom_scale(rv3d, scale);
|
||||
}
|
||||
else {
|
||||
view_zoom_to_window_xy_3d(v3d, region, rv3d->ofs, rv3d->dist, mval, delta);
|
||||
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(area, region);
|
||||
}
|
||||
}
|
||||
|
||||
ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int viewzoom_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
View3D *v3d;
|
||||
RegionView3D *rv3d;
|
||||
ScrArea *area;
|
||||
ARegion *region;
|
||||
|
||||
const int delta = RNA_int_get(op->ptr, "delta");
|
||||
|
||||
area = CTX_wm_area(C);
|
||||
region = CTX_wm_region(C);
|
||||
float xy[2];
|
||||
|
||||
/* compute direction vector for given zoom direction */
|
||||
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
|
||||
if (use_cursor_init) {
|
||||
xy[0] = (float)RNA_int_get(op->ptr, "mx");
|
||||
xy[1] = (float)RNA_int_get(op->ptr, "my");
|
||||
}
|
||||
else {
|
||||
xy[0] = (float)region->winx / 2.0f;
|
||||
xy[1] = (float)region->winy / 2.0f;
|
||||
}
|
||||
|
||||
v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
|
||||
view_zoom_to_window_xy_3d(v3d, region, rv3d->ofs, rv3d->dist, xy, delta);
|
||||
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(area, region);
|
||||
}
|
||||
|
||||
ED_view3d_camera_lock_sync(CTX_data_ensure_evaluated_depsgraph(C), v3d, rv3d);
|
||||
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int viewzoom_invoke_impl(bContext *C,
|
||||
ViewOpsData *vod,
|
||||
const wmEvent *event,
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
float xy[2];
|
||||
|
||||
/* Set to false to avoid contradiction with VIEWOPS_FLAG_ZOOM_TO_MOUSE */
|
||||
RNA_boolean_set(ptr, "use_cursor_init", false);
|
||||
|
||||
/* if one or the other zoom direction is not set */
|
||||
if (!RNA_struct_property_is_set(ptr, "mx") || !RNA_struct_property_is_set(ptr, "my")) {
|
||||
/* set xy to region local coordinates */
|
||||
if (vod->viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) {
|
||||
xy[0] = (float)event->mval[0];
|
||||
xy[1] = (float)event->mval[1];
|
||||
}
|
||||
else {
|
||||
xy[0] = (float)vod->region->winx / 2.0f;
|
||||
xy[1] = (float)vod->region->winy / 2.0f;
|
||||
}
|
||||
|
||||
RNA_int_set(ptr, "mx", (int)xy[0]);
|
||||
RNA_int_set(ptr, "my", (int)xy[1]);
|
||||
}
|
||||
else {
|
||||
copy_v2_fl2(xy, (float)RNA_int_get(ptr, "mx"), (float)RNA_int_get(ptr, "my"));
|
||||
}
|
||||
|
||||
if (RNA_struct_property_is_set(ptr, "delta")) {
|
||||
return viewzoom_apply_step(C, ptr, vod, xy);
|
||||
}
|
||||
else {
|
||||
/* we do not set the delta property. It is an int, so usually would be
|
||||
* 0 if rounded from a float */
|
||||
if (ELEM(event->type, MOUSEZOOM, MOUSEPAN)) {
|
||||
int move_xy[2];
|
||||
sub_v2_v2v2_int(move_xy, event->prev_xy, event->xy);
|
||||
if (event->type == MOUSEZOOM) {
|
||||
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
|
||||
move_xy[1] = move_xy[0];
|
||||
}
|
||||
|
||||
viewzoom_apply(vod, move_xy, USER_ZOOM_DOLLY,((U.uiflag & USER_ZOOM_INVERT) != 0)
|
||||
^ ((event->flag & WM_EVENT_SCROLL_INVERT) !=0), xy);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
if (U.viewzoom == USER_ZOOM_CONTINUE) {
|
||||
/* needs a timer to continue redrawing */
|
||||
vod->prev.time = PIL_check_seconds_timer();
|
||||
vod->timer = WM_event_timer_add(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
|
||||
}
|
||||
|
||||
vod->init.event_xy_offset[0] = xy[0] - (float)vod->region->winx / 2.0f;
|
||||
vod->init.event_xy_offset[1] = xy[1] - (float)vod->region->winy / 2.0f;
|
||||
vod->init.zfac = 0.0f;
|
||||
copy_v2_v2_int(vod->prev.event_xy, event->xy);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
/* viewdolly_invoke() copied this function, changes here may apply there */
|
||||
static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return view3d_navigate_invoke_impl(C, op, event, &ViewOpsType_zoom);
|
||||
}
|
||||
|
||||
void VIEW3D_OT_zoom(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Zoom View";
|
||||
ot->description = "Zoom in/out in the view";
|
||||
ot->idname = ViewOpsType_zoom.idname;
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = viewzoom_invoke;
|
||||
ot->exec = viewzoom_exec;
|
||||
ot->modal = view3d_navigate_modal_fn;
|
||||
ot->poll = view3d_zoom_or_dolly_poll;
|
||||
ot->cancel = view3d_navigate_cancel_fn;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
const ViewOpsType ViewOpsType_zoom = {
|
||||
/*flag*/ (VIEWOPS_FLAG_DEPTH_NAVIGATE | VIEWOPS_FLAG_ZOOM_TO_MOUSE),
|
||||
/*idname*/ "VIEW3D_OT_zoom",
|
||||
/*poll_fn*/ view3d_zoom_or_dolly_poll,
|
||||
/*init_fn*/ viewzoom_invoke_impl,
|
||||
/*apply_fn*/ viewzoom_modal_impl,
|
||||
};
|
|
@ -1136,7 +1136,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
|
|||
case TFM_MODAL_PROPSIZE:
|
||||
/* MOUSEPAN usage... */
|
||||
if (t->flag & T_PROP_EDIT) {
|
||||
float fac = 1.0f + 0.005f * (event->xy[1] - event->prev_xy[1]);
|
||||
float fac = 1.0f + 0.005f / UI_SCALE_FAC * WM_event_absolute_delta_y(event);
|
||||
t->prop_size *= fac;
|
||||
if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) {
|
||||
t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->clip_end),
|
||||
|
|
Loading…
Reference in New Issue