3DView: Use "real" angle for viewport roll

Since its introduction in {rB5c569d227b64}, the view roll was based on
horizontal movement only. Using a "real" angle not only feels more
natural but also has the benefit of getting more precission the further
away from the center you are (just like regular rotation, brush/stencil
rotation etc.). A similar thing has already been implemented in the
Grease Pencil Tools Addon, now make the blender standard roll the same.

Since this is not using the transform system, we are still lacking a
line in the viewport (this could be added but since this is always based
on the center of the view we dont necessarily need this), as well as the
additional Shift-extra-precission behavior.

Fixes T89883

Maniphest Tasks: T89883

Differential Revision: https://developer.blender.org/D12582
This commit is contained in:
Philipp Oeser 2021-09-20 18:11:52 +02:00
parent 8dcddbcc07
commit 69893ef27c
Notes: blender-bot 2023-02-14 05:53:42 +01:00
Referenced by commit 2a0db195c9, Fix viewport roll working wrong
Referenced by issue #96299, Rolling the viewport always use last selection as pivot point
Referenced by issue #89883, Bug? Inconsistency? Viewport roll use horizontal move instead angle
1 changed files with 14 additions and 11 deletions

View File

@ -38,6 +38,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_dial_2d.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@ -210,6 +211,9 @@ typedef struct ViewOpsData {
* If we want the value before running the operator, add a separate member.
*/
char persp;
/** Used for roll */
Dial *dial;
} init;
/** Previous state (previous modal event handled). */
@ -577,6 +581,10 @@ static void viewops_data_free(bContext *C, wmOperator *op)
WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer);
}
if (vod->init.dial) {
MEM_SAFE_FREE(vod->init.dial);
}
MEM_freeN(vod);
op->customdata = NULL;
}
@ -4352,18 +4360,9 @@ static void view_roll_angle(
rv3d->view = RV3D_VIEW_USER;
}
static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
static void viewroll_apply(ViewOpsData *vod, int x, int y)
{
float angle = 0.0;
{
float len1, len2, tot;
tot = vod->region->winrct.xmax - vod->region->winrct.xmin;
len1 = (vod->region->winrct.xmax - x) / tot;
len2 = (vod->region->winrct.xmax - vod->init.event_xy[0]) / tot;
angle = (len1 - len2) * (float)M_PI * 4.0f;
}
float angle = BLI_dial_angle(vod->init.dial, (const float[2]){x, y});
if (angle != 0.0f) {
view_roll_angle(vod->region, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle);
@ -4517,6 +4516,10 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
viewops_data_alloc(C, op);
viewops_data_create(C, op, event, viewops_flag_from_prefs());
vod = op->customdata;
vod->init.dial = BLI_dial_init(
(const float[2]){(vod->region->winrct.xmax - vod->region->winrct.xmin) / 2,
(vod->region->winrct.ymax - vod->region->winrct.ymin) / 2},
FLT_EPSILON);
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);