UI: offset scale gizmos instead of scaling their shape

Scaling handles while dragging could be distracting, especially at
extreme values where handles could become large on-screen.

Now all gizmos are shown while scaling.

GIZMO_GT_arrow_3d now now support changing their length while being
dragged as well as negative lengths.
This commit is contained in:
Campbell Barton 2022-06-06 12:38:34 +10:00
parent bb34afac56
commit 011d9cce19
2 changed files with 45 additions and 27 deletions

View File

@ -58,6 +58,11 @@ typedef struct ArrowGizmo3D {
GizmoCommonData data;
} ArrowGizmo3D;
typedef struct ArrowGizmoInteraction {
GizmoInteraction inter;
float init_arrow_length;
} ArrowGizmoInteraction;
/* -------------------------------------------------------------------- */
static void gizmo_arrow_matrix_basis_get(const wmGizmo *gz, float r_matrix[4][4])
@ -68,7 +73,10 @@ static void gizmo_arrow_matrix_basis_get(const wmGizmo *gz, float r_matrix[4][4]
madd_v3_v3fl(r_matrix[3], arrow->gizmo.matrix_basis[2], arrow->data.offset);
}
static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const float color[4])
static void arrow_draw_geom(const ArrowGizmo3D *arrow,
const bool select,
const float color[4],
const float arrow_length)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
bool unbind_shader = true;
@ -111,8 +119,6 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
#ifdef USE_GIZMO_CUSTOM_ARROWS
wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_arrow, select, color);
#else
const float arrow_length = RNA_float_get(arrow->gizmo.ptr, "length");
const float vec[2][3] = {
{0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, arrow_length},
@ -176,6 +182,7 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, const bool select, const
static void arrow_draw_intern(ArrowGizmo3D *arrow, const bool select, const bool highlight)
{
wmGizmo *gz = &arrow->gizmo;
const float arrow_length = RNA_float_get(gz->ptr, "length");
float color[4];
float matrix_final[4][4];
@ -186,19 +193,20 @@ static void arrow_draw_intern(ArrowGizmo3D *arrow, const bool select, const bool
GPU_matrix_push();
GPU_matrix_mul(matrix_final);
GPU_blend(GPU_BLEND_ALPHA);
arrow_draw_geom(arrow, select, color);
arrow_draw_geom(arrow, select, color, arrow_length);
GPU_blend(GPU_BLEND_NONE);
GPU_matrix_pop();
if (gz->interaction_data) {
GizmoInteraction *inter = gz->interaction_data;
ArrowGizmoInteraction *arrow_inter = gz->interaction_data;
GPU_matrix_push();
GPU_matrix_mul(inter->init_matrix_final);
GPU_matrix_mul(arrow_inter->inter.init_matrix_final);
GPU_blend(GPU_BLEND_ALPHA);
arrow_draw_geom(arrow, select, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f});
arrow_draw_geom(
arrow, select, (const float[4]){0.5f, 0.5f, 0.5f, 0.5f}, arrow_inter->init_arrow_length);
GPU_blend(GPU_BLEND_NONE);
GPU_matrix_pop();
@ -380,7 +388,7 @@ static void gizmo_arrow_setup(wmGizmo *gz)
static int gizmo_arrow_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *event)
{
ArrowGizmo3D *arrow = (ArrowGizmo3D *)gz;
GizmoInteraction *inter = MEM_callocN(sizeof(GizmoInteraction), __func__);
GizmoInteraction *inter = MEM_callocN(sizeof(ArrowGizmoInteraction), __func__);
wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "offset");
/* Some gizmos don't use properties. */
@ -396,6 +404,8 @@ static int gizmo_arrow_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *e
gizmo_arrow_matrix_basis_get(gz, inter->init_matrix_basis);
WM_gizmo_calc_matrix_final(gz, inter->init_matrix_final);
((ArrowGizmoInteraction *)inter)->init_arrow_length = RNA_float_get(gz->ptr, "length");
gz->interaction_data = inter;
return OPERATOR_RUNNING_MODAL;
@ -520,7 +530,8 @@ static void GIZMO_GT_arrow_3d(wmGizmoType *gzt)
"");
RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform_items, 0, "Transform", "");
RNA_def_float(gzt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
RNA_def_float(
gzt->srna, "length", 1.0f, -FLT_MAX, FLT_MAX, "Arrow Line Length", "", -FLT_MAX, FLT_MAX);
RNA_def_float_vector(
gzt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX);

View File

@ -1378,6 +1378,11 @@ void drawDial3d(const TransInfo *t)
/** \name Transform Gizmo
* \{ */
/** Scale of the two-axis planes. */
#define MAN_AXIS_SCALE_PLANE_SCALE 0.07f
/** Offset of the two-axis planes, depends on the gizmos scale. Define to avoid repeating. */
#define MAN_AXIS_SCALE_PLANE_OFFSET 7.0f
static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup)
{
GizmoGroup *ggd;
@ -1503,12 +1508,10 @@ static int gizmo_modal(bContext *C,
/* Showing axes which aren't being manipulated doesn't always work so well.
*
* - For rotate: global axis will reset after finish.
* Also, gimbal axis isn't properly recalculated while transforming.
* - For scale: showing the other axes isn't so useful and can be distracting
* since the handles can get very big-small.
* For rotate: global axis will reset after finish.
* Also, gimbal axis isn't properly recalculated while transforming.
*/
if (ELEM(axis_type, MAN_AXES_ROTATE, MAN_AXES_SCALE)) {
if (axis_type == MAN_AXES_ROTATE) {
MAN_ITER_AXES_BEGIN (axis, axis_idx) {
if (axis == widget) {
continue;
@ -1608,9 +1611,8 @@ static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *gzgroup)
case MAN_AXIS_SCALE_XY:
case MAN_AXIS_SCALE_YZ:
case MAN_AXIS_SCALE_ZX: {
const float ofs_ax = 7.0f;
const float ofs[3] = {ofs_ax, ofs_ax, 0.0f};
WM_gizmo_set_scale(axis, 0.07f);
const float ofs[3] = {MAN_AXIS_SCALE_PLANE_OFFSET, MAN_AXIS_SCALE_PLANE_OFFSET, 0.0f};
WM_gizmo_set_scale(axis, MAN_AXIS_SCALE_PLANE_SCALE);
WM_gizmo_set_matrix_offset_location(axis, ofs);
WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
break;
@ -1762,7 +1764,6 @@ static void gizmo_refresh_from_matrix(wmGizmoGroup *gzgroup,
else {
WM_gizmo_set_matrix_rotation_from_z_axis(axis, z_axis);
}
RNA_float_set(axis->ptr, "length", len);
if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
if (ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
@ -1770,15 +1771,19 @@ static void gizmo_refresh_from_matrix(wmGizmoGroup *gzgroup,
start_co[2] += 0.215f;
}
}
if (scale) {
if (axis_type == MAN_AXES_SCALE) {
len = ((start_co[2] + len) * scale[aidx_norm]) - start_co[2];
}
}
RNA_float_set(axis->ptr, "length", len);
WM_gizmo_set_matrix_offset_location(axis, start_co);
WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true);
if (scale) {
if (axis_type == MAN_AXES_SCALE) {
mul_v3_fl(axis->matrix_basis[2], scale[aidx_norm]);
}
}
break;
}
case MAN_AXIS_ROT_X:
@ -1798,11 +1803,13 @@ static void gizmo_refresh_from_matrix(wmGizmoGroup *gzgroup,
const float *z_axis = twmat[aidx_norm];
WM_gizmo_set_matrix_rotation_from_yz_axis(axis, y_axis, z_axis);
if (scale) {
if (axis_type == MAN_AXES_SCALE) {
mul_v3_fl(axis->matrix_basis[0], scale[aidx_norm_x]);
mul_v3_fl(axis->matrix_basis[1], scale[aidx_norm_y]);
if (axis_type == MAN_AXES_SCALE) {
float ofs[3] = {MAN_AXIS_SCALE_PLANE_OFFSET, MAN_AXIS_SCALE_PLANE_OFFSET, 0.0f};
if (scale) {
ofs[0] *= scale[aidx_norm_x];
ofs[1] *= scale[aidx_norm_y];
}
WM_gizmo_set_matrix_offset_location(axis, ofs);
}
break;
}