From 97c05aa288f7f499beefc041a161bd2258c18328 Mon Sep 17 00:00:00 2001 From: mano-wii Date: Thu, 13 Apr 2023 20:23:03 +0200 Subject: [PATCH] Transform: improve visualization when dragging Gizmos Apply the changes suggested at #103782 It includes: - Draw dot at the origin the active gizmo - Hide other gizmos while dragging (except the move arrows) Other changes: - Draw shadow for the move and scale circle gizmos (while transforming) Pull Request: https://projects.blender.org/blender/blender/pulls/104624 --- .../gizmo_library/gizmo_library_intern.h | 2 + .../gizmo_library/gizmo_types/arrow3d_gizmo.c | 40 ++- .../gizmo_library/gizmo_types/dial3d_gizmo.c | 1 - .../gizmo_library/gizmo_types/move3d_gizmo.c | 5 +- .../gizmo_types/primitive3d_gizmo.c | 197 ++++++++++++--- .../editors/include/ED_gizmo_library.h | 4 + .../editors/transform/transform_gizmo_3d.cc | 234 +++++++++--------- 7 files changed, 329 insertions(+), 154 deletions(-) diff --git a/source/blender/editors/gizmo_library/gizmo_library_intern.h b/source/blender/editors/gizmo_library/gizmo_library_intern.h index 4c7fe7fbd7d..a8ce1473263 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_intern.h +++ b/source/blender/editors/gizmo_library/gizmo_library_intern.h @@ -7,6 +7,8 @@ #pragma once +#define DIAL_RESOLUTION 48 + /** * Data for common interactions. Used in gizmo_library_utils.c functions. */ diff --git a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c index b1f4281e8a9..1cb3cdef821 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c @@ -48,7 +48,7 @@ #include "../gizmo_library_intern.h" /* to use custom arrows exported to geom_arrow_gizmo.c */ -//#define USE_GIZMO_CUSTOM_ARROWS +// #define USE_GIZMO_CUSTOM_ARROWS /* Margin to add when selecting the arrow. */ #define ARROW_SELECT_THRESHOLD_PX (5) @@ -115,6 +115,29 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, immUniform1f("lineWidth", arrow->gizmo.line_width * U.pixelsize); wm_gizmo_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GPU_PRIM_LINE_LOOP); } + else if (draw_style == ED_GIZMO_ARROW_STYLE_PLANE) { + const float scale = 0.1f; + const float verts[4][3] = { + {0, 0, 0}, + {scale, 0, scale}, + {0, 0, 2 * scale}, + {-scale, 0, scale}, + }; + + const float color_inner[4] = {UNPACK3(color), color[3] * 0.5f}; + + /* Translate to line end. */ + GPU_matrix_push(); + GPU_matrix_translate_3f(0.0f, 0.0f, arrow_length); + + immUniform1f("lineWidth", arrow->gizmo.line_width * U.pixelsize); + wm_gizmo_vec_draw(color, verts, ARRAY_SIZE(verts), pos, GPU_PRIM_LINE_LOOP); + + immUnbindProgram(); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + wm_gizmo_vec_draw(color_inner, verts, ARRAY_SIZE(verts), pos, GPU_PRIM_TRI_FAN); + GPU_matrix_pop(); + } else { #ifdef USE_GIZMO_CUSTOM_ARROWS wm_gizmo_geometryinfo_draw(&wm_gizmo_geom_data_arrow, select, color); @@ -177,6 +200,19 @@ static void arrow_draw_geom(const ArrowGizmo3D *arrow, if (unbind_shader) { immUnbindProgram(); } + + if (draw_options & ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN) { + const float point_size = 10 * U.pixelsize; + GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immUniform1f("size", point_size); + immUniformColor4fv(color); + immBegin(GPU_PRIM_POINTS, 1); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); + immEnd(); + immUnbindProgram(); + GPU_program_point_size(false); + } } static void arrow_draw_intern(ArrowGizmo3D *arrow, const bool select, const bool highlight) @@ -504,10 +540,12 @@ static void GIZMO_GT_arrow_3d(wmGizmoType *gzt) {ED_GIZMO_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""}, {ED_GIZMO_ARROW_STYLE_BOX, "BOX", 0, "Box", ""}, {ED_GIZMO_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""}, + {ED_GIZMO_ARROW_STYLE_PLANE, "PLANE", 0, "Plane", ""}, {0, NULL, 0, NULL, NULL}, }; static EnumPropertyItem rna_enum_draw_options_items[] = { {ED_GIZMO_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""}, + {ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN, "ORIGIN", 0, "Origin", ""}, {0, NULL, 0, NULL, NULL}, }; static EnumPropertyItem rna_enum_transform_items[] = { diff --git a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c index 84dcf495f6d..6d2cdd45c41 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c @@ -71,7 +71,6 @@ typedef struct DialInteraction { } DialInteraction; #define DIAL_WIDTH 1.0f -#define DIAL_RESOLUTION 48 /* Could make option, negative to clip more (don't show when view aligned). */ #define DIAL_CLIP_BIAS 0.02 diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c index f6ae02dd010..16493366b3f 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c @@ -42,6 +42,7 @@ #include "../gizmo_library_intern.h" #define MVAL_MAX_PX_DIST 12.0f +#define RING_2D_RESOLUTION 32 typedef struct MoveGizmo3D { wmGizmo gizmo; @@ -116,10 +117,10 @@ static void move_geom_draw(const wmGizmo *gz, if (draw_style == ED_GIZMO_MOVE_STYLE_RING_2D) { if (filled) { - imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, radius, DIAL_RESOLUTION); + imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, radius, RING_2D_RESOLUTION); } else { - imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, radius, DIAL_RESOLUTION); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, radius, RING_2D_RESOLUTION); } } else if (draw_style == ED_GIZMO_MOVE_STYLE_CROSS_2D) { diff --git a/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c index 257e5fbf9e7..37b1d784190 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/primitive3d_gizmo.c @@ -15,6 +15,8 @@ #include "BLI_math.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "BKE_context.h" @@ -42,36 +44,135 @@ static float verts_plane[4][3] = { {-1, 1, 0}, }; +typedef struct PrimitiveGizmo3D { + wmGizmo gizmo; + + int draw_style; + float arc_inner_factor; + bool draw_inner; +} PrimitiveGizmo3D; + /* -------------------------------------------------------------------- */ +/** \name RNA callbacks */ -static void gizmo_primitive_draw_geom(const float col_inner[4], - const float col_outer[4], - const int draw_style) +static PrimitiveGizmo3D *gizmo_primitive_rna_find_operator(PointerRNA *ptr) { - float(*verts)[3]; - uint vert_count = 0; - - if (draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) { - verts = verts_plane; - vert_count = ARRAY_SIZE(verts_plane); - } - - if (vert_count > 0) { - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - wm_gizmo_vec_draw(col_inner, verts, vert_count, pos, GPU_PRIM_TRI_FAN); - wm_gizmo_vec_draw(col_outer, verts, vert_count, pos, GPU_PRIM_LINE_LOOP); - immUnbindProgram(); - } + return (PrimitiveGizmo3D *)gizmo_find_from_properties(ptr->data, SPACE_TYPE_ANY, RGN_TYPE_ANY); } -static void gizmo_primitive_draw_intern(wmGizmo *gz, - const bool UNUSED(select), - const bool highlight) +static int gizmo_primitive_rna__draw_style_get_fn(struct PointerRNA *ptr, + struct PropertyRNA *UNUSED(prop)) { + PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr); + return gz_prim->draw_style; +} + +static void gizmo_primitive_rna__draw_style_set_fn(struct PointerRNA *ptr, + struct PropertyRNA *UNUSED(prop), + int value) +{ + PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr); + gz_prim->draw_style = value; +} + +static float gizmo_primitive_rna__arc_inner_factor_get_fn(struct PointerRNA *ptr, + struct PropertyRNA *UNUSED(prop)) +{ + PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr); + return gz_prim->arc_inner_factor; +} + +static void gizmo_primitive_rna__arc_inner_factor_set_fn(struct PointerRNA *ptr, + struct PropertyRNA *UNUSED(prop), + float value) +{ + PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr); + gz_prim->arc_inner_factor = value; +} + +static bool gizmo_primitive_rna__draw_inner_get_fn(struct PointerRNA *ptr, + struct PropertyRNA *UNUSED(prop)) +{ + PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr); + return gz_prim->draw_inner; +} + +static void gizmo_primitive_rna__draw_inner_set_fn(struct PointerRNA *ptr, + struct PropertyRNA *UNUSED(prop), + bool value) +{ + PrimitiveGizmo3D *gz_prim = gizmo_primitive_rna_find_operator(ptr); + gz_prim->draw_inner = value; +} + +/* -------------------------------------------------------------------- */ + +static void gizmo_primitive_draw_geom(PrimitiveGizmo3D *gz_prim, + const float col_inner[4], + const float col_outer[4], + const int nsegments, + const bool draw_inner) +{ + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + const bool use_polyline_shader = gz_prim->gizmo.line_width > 1.0f; + + if (draw_inner || !use_polyline_shader) { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + } + + if (draw_inner) { + if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) { + wm_gizmo_vec_draw(col_inner, verts_plane, ARRAY_SIZE(verts_plane), pos, GPU_PRIM_TRI_FAN); + } + else { + immUniformColor4fv(col_inner); + if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_CIRCLE) { + imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, 1.0f, nsegments); + } + else { + BLI_assert(gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_ANNULUS); + imm_draw_disk_partial_fill_3d( + pos, 0.0f, 0.0f, 0.0f, gz_prim->arc_inner_factor, 1.0f, nsegments, 0.0f, 360.0f); + } + } + } + + /* Draw outline. */ + + if (use_polyline_shader) { + if (draw_inner) { + immUnbindProgram(); + } + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + + float viewport[4]; + GPU_viewport_size_get_f(viewport); + immUniform2fv("viewportSize", &viewport[2]); + immUniform1f("lineWidth", gz_prim->gizmo.line_width * U.pixelsize); + } + + if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_PLANE) { + wm_gizmo_vec_draw(col_outer, verts_plane, ARRAY_SIZE(verts_plane), pos, GPU_PRIM_LINE_LOOP); + } + else { + immUniformColor4fv(col_outer); + if (gz_prim->draw_style == ED_GIZMO_PRIMITIVE_STYLE_CIRCLE) { + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, nsegments); + } + else { + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, gz_prim->arc_inner_factor, nsegments); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, nsegments); + } + } + immUnbindProgram(); +} + +static void gizmo_primitive_draw_intern(wmGizmo *gz, const bool select, const bool highlight) +{ + PrimitiveGizmo3D *gz_prim = (PrimitiveGizmo3D *)gz; + float color_inner[4], color_outer[4]; float matrix_final[4][4]; - const int draw_style = RNA_enum_get(gz->ptr, "draw_style"); gizmo_color_get(gz, highlight, color_outer); copy_v4_v4(color_inner, color_outer); @@ -79,12 +180,15 @@ static void gizmo_primitive_draw_intern(wmGizmo *gz, WM_gizmo_calc_matrix_final(gz, matrix_final); + GPU_blend(GPU_BLEND_ALPHA); GPU_matrix_push(); GPU_matrix_mul(matrix_final); - GPU_blend(GPU_BLEND_ALPHA); - gizmo_primitive_draw_geom(color_inner, color_outer, draw_style); - GPU_blend(GPU_BLEND_NONE); + gizmo_primitive_draw_geom(gz_prim, + color_inner, + color_outer, + select ? 24 : DIAL_RESOLUTION, + gz_prim->draw_inner || select); GPU_matrix_pop(); @@ -98,12 +202,12 @@ static void gizmo_primitive_draw_intern(wmGizmo *gz, GPU_matrix_push(); GPU_matrix_mul(inter->init_matrix_final); - GPU_blend(GPU_BLEND_ALPHA); - gizmo_primitive_draw_geom(color_inner, color_outer, draw_style); - GPU_blend(GPU_BLEND_NONE); + gizmo_primitive_draw_geom( + gz_prim, color_inner, color_outer, DIAL_RESOLUTION, gz_prim->draw_inner); GPU_matrix_pop(); } + GPU_blend(GPU_BLEND_NONE); } static void gizmo_primitive_draw_select(const bContext *UNUSED(C), wmGizmo *gz, int select_id) @@ -120,6 +224,12 @@ static void gizmo_primitive_draw(const bContext *UNUSED(C), wmGizmo *gz) static void gizmo_primitive_setup(wmGizmo *gz) { gz->flag |= WM_GIZMO_DRAW_MODAL; + + /* Default Values. */ + PrimitiveGizmo3D *gz_prim = (PrimitiveGizmo3D *)gz; + gz_prim->draw_style = ED_GIZMO_PRIMITIVE_STYLE_PLANE; + gz_prim->arc_inner_factor = true; + gz_prim->draw_inner = true; } static int gizmo_primitive_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *UNUSED(event)) @@ -148,18 +258,35 @@ static void GIZMO_GT_primitive_3d(wmGizmoType *gzt) gzt->setup = gizmo_primitive_setup; gzt->invoke = gizmo_primitive_invoke; - gzt->struct_size = sizeof(wmGizmo); + gzt->struct_size = sizeof(PrimitiveGizmo3D); static EnumPropertyItem rna_enum_draw_style[] = { {ED_GIZMO_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""}, + {ED_GIZMO_PRIMITIVE_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""}, + {ED_GIZMO_PRIMITIVE_STYLE_ANNULUS, "ANNULUS", 0, "Annulus", ""}, {0, NULL, 0, NULL, NULL}, }; - RNA_def_enum(gzt->srna, - "draw_style", - rna_enum_draw_style, - ED_GIZMO_PRIMITIVE_STYLE_PLANE, - "Draw Style", - ""); + + PropertyRNA *prop; + prop = RNA_def_enum(gzt->srna, + "draw_style", + rna_enum_draw_style, + ED_GIZMO_PRIMITIVE_STYLE_PLANE, + "Draw Style", + ""); + RNA_def_property_enum_funcs_runtime( + prop, gizmo_primitive_rna__draw_style_get_fn, gizmo_primitive_rna__draw_style_set_fn, NULL); + + prop = RNA_def_float_factor( + gzt->srna, "arc_inner_factor", 0.0f, 0.0f, FLT_MAX, "Arc Inner Factor", "", 0.0f, 1.0f); + RNA_def_property_float_funcs_runtime(prop, + gizmo_primitive_rna__arc_inner_factor_get_fn, + gizmo_primitive_rna__arc_inner_factor_set_fn, + NULL); + + prop = RNA_def_boolean(gzt->srna, "draw_inner", true, "Draw Inner", ""); + RNA_def_property_boolean_funcs_runtime( + prop, gizmo_primitive_rna__draw_inner_get_fn, gizmo_primitive_rna__draw_inner_set_fn); } void ED_gizmotypes_primitive_3d(void) diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h index 9430aa348ab..2826aa9a313 100644 --- a/source/blender/editors/include/ED_gizmo_library.h +++ b/source/blender/editors/include/ED_gizmo_library.h @@ -64,6 +64,7 @@ enum { ED_GIZMO_ARROW_STYLE_CROSS = 1, ED_GIZMO_ARROW_STYLE_BOX = 2, ED_GIZMO_ARROW_STYLE_CONE = 3, + ED_GIZMO_ARROW_STYLE_PLANE = 4, }; /* transform */ @@ -78,6 +79,7 @@ enum { enum { /* Show arrow stem. */ ED_GIZMO_ARROW_DRAW_FLAG_STEM = (1 << 0), + ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN = (1 << 1), }; /** @@ -233,6 +235,8 @@ enum { enum { ED_GIZMO_PRIMITIVE_STYLE_PLANE = 0, + ED_GIZMO_PRIMITIVE_STYLE_CIRCLE, + ED_GIZMO_PRIMITIVE_STYLE_ANNULUS, }; /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/transform/transform_gizmo_3d.cc b/source/blender/editors/transform/transform_gizmo_3d.cc index 13b6d3ca957..af6db57e275 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.cc +++ b/source/blender/editors/transform/transform_gizmo_3d.cc @@ -1227,9 +1227,7 @@ static void gizmo_3d_dial_matrixbasis_calc(const ARegion *region, * \{ */ /** 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 +#define MAN_AXIS_SCALE_PLANE_SCALE 0.7f static void rotation_get_fn(const wmGizmo * /*gz*/, wmGizmoProperty *gz_prop, void *value) { @@ -1273,21 +1271,21 @@ static void gizmo_3d_setup_default_matrix(wmGizmo *axis, const int axis_idx) case MAN_AXIS_TRANS_XY: case MAN_AXIS_SCALE_XY: - copy_v3_fl3(matrix[0], MAN_AXIS_SCALE_PLANE_SCALE, 0.0f, 0.0f); - copy_v3_fl3(matrix[1], 0.0f, MAN_AXIS_SCALE_PLANE_SCALE, 0.0f); - copy_v3_fl3(matrix[2], 0.0f, 0.0f, MAN_AXIS_SCALE_PLANE_SCALE); + copy_v3_fl3(matrix[0], -M_SQRT1_2, M_SQRT1_2, 0.0f); + copy_v3_fl3(matrix[1], 0.0f, 0.0f, 1.0f); + copy_v3_fl3(matrix[2], M_SQRT1_2, M_SQRT1_2, 0.0f); break; case MAN_AXIS_TRANS_YZ: case MAN_AXIS_SCALE_YZ: - copy_v3_fl3(matrix[0], 0.0f, 0.0f, MAN_AXIS_SCALE_PLANE_SCALE); - copy_v3_fl3(matrix[1], 0.0f, MAN_AXIS_SCALE_PLANE_SCALE, 0.0f); - copy_v3_fl3(matrix[2], -MAN_AXIS_SCALE_PLANE_SCALE, 0.0f, 0.0f); + copy_v3_fl3(matrix[0], 0.0f, -M_SQRT1_2, M_SQRT1_2); + copy_v3_fl3(matrix[1], 1.0f, 0.0f, 0.0f); + copy_v3_fl3(matrix[2], 0, M_SQRT1_2, M_SQRT1_2); break; - case MAN_AXIS_TRANS_ZX: case MAN_AXIS_SCALE_ZX: - copy_v3_fl3(matrix[0], MAN_AXIS_SCALE_PLANE_SCALE, 0.0f, 0.0f); - copy_v3_fl3(matrix[1], 0.0f, 0.0f, MAN_AXIS_SCALE_PLANE_SCALE); - copy_v3_fl3(matrix[2], 0.0f, -MAN_AXIS_SCALE_PLANE_SCALE, 0.0f); + case MAN_AXIS_TRANS_ZX: + copy_v3_fl3(matrix[0], M_SQRT1_2, 0.0f, -M_SQRT1_2); + copy_v3_fl3(matrix[1], 0.0f, 1.0f, 0.0f); + copy_v3_fl3(matrix[2], M_SQRT1_2, 0.0f, M_SQRT1_2); break; case MAN_AXIS_TRANS_C: @@ -1299,22 +1297,6 @@ static void gizmo_3d_setup_default_matrix(wmGizmo *axis, const int axis_idx) } copy_m4_m3(axis->matrix_offset, matrix); - - switch (axis_idx) { - case MAN_AXIS_TRANS_XY: - case MAN_AXIS_TRANS_YZ: - case MAN_AXIS_TRANS_ZX: - case MAN_AXIS_SCALE_XY: - case MAN_AXIS_SCALE_YZ: - case MAN_AXIS_SCALE_ZX: { - float offs[3]; - add_v3_v3v3(offs, axis->matrix_offset[0], axis->matrix_offset[1]); - mul_v3_fl(offs, MAN_AXIS_SCALE_PLANE_OFFSET); - WM_gizmo_set_matrix_offset_location(axis, offs); - } break; - default: - return; - } } static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx) @@ -1334,38 +1316,39 @@ static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx) RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_BOX); RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_ARROW_DRAW_FLAG_STEM); break; - - /* Primitive. */ case MAN_AXIS_TRANS_XY: case MAN_AXIS_TRANS_YZ: case MAN_AXIS_TRANS_ZX: case MAN_AXIS_SCALE_XY: case MAN_AXIS_SCALE_YZ: case MAN_AXIS_SCALE_ZX: - RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_PRIMITIVE_STYLE_PLANE); - WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, true); + RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_PLANE); + RNA_enum_set(axis->ptr, "draw_options", 0); + RNA_float_set(axis->ptr, "length", MAN_AXIS_SCALE_PLANE_SCALE); break; - /* Dial. */ + /* Primitive. */ case MAN_AXIS_TRANS_C: - RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT); - WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_MODAL, true); + RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_PRIMITIVE_STYLE_CIRCLE); + RNA_boolean_set(axis->ptr, "draw_inner", false); WM_gizmo_set_scale(axis, 0.2f); /* Prevent axis gizmos overlapping the center point, see: #63744. */ axis->select_bias = 2.0f; break; case MAN_AXIS_SCALE_C: - RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT); + RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_PRIMITIVE_STYLE_ANNULUS); + RNA_boolean_set(axis->ptr, "draw_inner", false); - /* Use 1/6 since this is '0.2' if the main scale is 1.2. */ - RNA_float_set(axis->ptr, "arc_inner_factor", 1.0 / 6.0); - WM_gizmo_set_scale(axis, 1.2f); + /* Use 6 since this is '1.2' if the main scale is 0.2. */ + RNA_float_set(axis->ptr, "arc_inner_factor", 6.0f); + WM_gizmo_set_scale(axis, 0.2f); /* Prevent axis gizmos overlapping the center point, see: #63744. */ axis->select_bias = -2.0f; break; + /* Dial. */ case MAN_AXIS_ROT_X: case MAN_AXIS_ROT_Y: case MAN_AXIS_ROT_Z: @@ -1385,11 +1368,12 @@ static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx) } switch (axis_idx) { - case MAN_AXIS_ROT_X: - case MAN_AXIS_ROT_Y: - case MAN_AXIS_ROT_Z: - /* Increased line width for better display. */ - WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH + 1.0f); + case MAN_AXIS_TRANS_X: + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_SCALE_X: + case MAN_AXIS_SCALE_Y: + WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH); break; case MAN_AXIS_TRANS_XY: case MAN_AXIS_TRANS_YZ: @@ -1399,6 +1383,12 @@ static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx) case MAN_AXIS_SCALE_ZX: WM_gizmo_set_line_width(axis, 1.0f); break; + case MAN_AXIS_ROT_X: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_ROT_Z: + /* Increased line width for better display. */ + WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH + 1.0f); + break; default: WM_gizmo_set_line_width(axis, GIZMO_AXIS_LINE_WIDTH); break; @@ -1462,9 +1452,42 @@ static void gizmo_3d_setup_draw_from_twtype(wmGizmo *axis, const int axis_idx, c } } -static void gizmo_3d_setup_draw_modal(wmGizmo *axis, const int axis_idx) +static void gizmo_3d_setup_draw_modal(wmGizmo *axis, const int axis_idx, const int twtype) { const short axis_type = gizmo_get_axis_type(axis_idx); + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_SCALE_X: + case MAN_AXIS_SCALE_Y: + case MAN_AXIS_SCALE_Z: { + + float end, start_co[3] = {0.0f, 0.0f, 0.0f}; + gizmo_line_range(twtype, axis_type, NULL, &end); + RNA_float_set(axis->ptr, "length", end); + RNA_enum_set(axis->ptr, + "draw_options", + ED_GIZMO_ARROW_DRAW_FLAG_STEM | ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN); + WM_gizmo_set_matrix_offset_location(axis, start_co); + WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_OFFSET_SCALE, false); + break; + } + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_XY: + case MAN_AXIS_SCALE_YZ: + case MAN_AXIS_SCALE_ZX: + RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN); + break; + case MAN_AXIS_SCALE_C: + RNA_enum_set(axis->ptr, "draw_style", ED_GIZMO_PRIMITIVE_STYLE_CIRCLE); + break; + default: + break; + } + switch (axis_type) { case MAN_AXES_ROTATE: { PropertyRNA *prop = RNA_struct_find_property(axis->ptr, "draw_options"); @@ -1510,15 +1533,15 @@ static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup) /* add/init widgets - order matters! */ GIZMO_NEW_DIAL(MAN_AXIS_ROT_T); - GIZMO_NEW_DIAL(MAN_AXIS_SCALE_C); + GIZMO_NEW_PRIM(MAN_AXIS_SCALE_C); GIZMO_NEW_ARROW(MAN_AXIS_SCALE_X); GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Y); GIZMO_NEW_ARROW(MAN_AXIS_SCALE_Z); - GIZMO_NEW_PRIM(MAN_AXIS_SCALE_XY); - GIZMO_NEW_PRIM(MAN_AXIS_SCALE_YZ); - GIZMO_NEW_PRIM(MAN_AXIS_SCALE_ZX); + GIZMO_NEW_ARROW(MAN_AXIS_SCALE_XY); + GIZMO_NEW_ARROW(MAN_AXIS_SCALE_YZ); + GIZMO_NEW_ARROW(MAN_AXIS_SCALE_ZX); GIZMO_NEW_DIAL(MAN_AXIS_ROT_X); GIZMO_NEW_DIAL(MAN_AXIS_ROT_Y); @@ -1527,15 +1550,15 @@ static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup) /* init screen aligned widget last here, looks better, behaves better */ GIZMO_NEW_DIAL(MAN_AXIS_ROT_C); - GIZMO_NEW_DIAL(MAN_AXIS_TRANS_C); + GIZMO_NEW_PRIM(MAN_AXIS_TRANS_C); GIZMO_NEW_ARROW(MAN_AXIS_TRANS_X); GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Y); GIZMO_NEW_ARROW(MAN_AXIS_TRANS_Z); - GIZMO_NEW_PRIM(MAN_AXIS_TRANS_XY); - GIZMO_NEW_PRIM(MAN_AXIS_TRANS_YZ); - GIZMO_NEW_PRIM(MAN_AXIS_TRANS_ZX); + GIZMO_NEW_ARROW(MAN_AXIS_TRANS_XY); + GIZMO_NEW_ARROW(MAN_AXIS_TRANS_YZ); + GIZMO_NEW_ARROW(MAN_AXIS_TRANS_ZX); MAN_ITER_AXES_BEGIN (axis, axis_idx) { gizmo_3d_setup_draw_default(axis, axis_idx); @@ -1763,11 +1786,9 @@ static void gizmo_refresh_from_matrix(wmGizmo *axis, case MAN_AXIS_SCALE_ZX: copy_m4_m4(axis->matrix_basis, twmat); if (scale) { - float offs[3]; - add_v3_v3v3(offs, axis->matrix_offset[0], axis->matrix_offset[1]); - mul_v3_fl(offs, MAN_AXIS_SCALE_PLANE_OFFSET); - mul_v3_v3(offs, scale); - WM_gizmo_set_matrix_offset_location(axis, offs); + RNA_float_set(axis->ptr, + "length", + MAN_AXIS_SCALE_PLANE_SCALE * scale[aidx_norm == 2 ? 0 : aidx_norm + 1]); } break; case MAN_AXIS_SCALE_X: @@ -1775,23 +1796,29 @@ static void gizmo_refresh_from_matrix(wmGizmo *axis, case MAN_AXIS_SCALE_Z: copy_m4_m4(axis->matrix_basis, twmat); if (scale) { - float start, end; - gizmo_line_range(twtype, axis_type, &start, &end); - RNA_float_set(axis->ptr, "length", (end - start) * scale[aidx_norm]); + float end; + gizmo_line_range(twtype, axis_type, NULL, &end); + RNA_float_set(axis->ptr, "length", end * scale[aidx_norm]); } + break; case MAN_AXIS_TRANS_X: case MAN_AXIS_TRANS_Y: case MAN_AXIS_TRANS_Z: copy_m4_m4(axis->matrix_basis, twmat); break; + case MAN_AXIS_SCALE_C: + WM_gizmo_set_matrix_location(axis, twmat[3]); + if (scale) { + WM_gizmo_set_scale(axis, 0.2f * scale[0]); + } + break; case MAN_AXIS_ROT_X: case MAN_AXIS_ROT_Y: case MAN_AXIS_ROT_Z: copy_m4_m4(axis->matrix_basis, twmat); orthogonalize_m4(axis->matrix_basis, aidx_norm); break; - case MAN_AXIS_SCALE_C: case MAN_AXIS_ROT_C: case MAN_AXIS_ROT_T: default: @@ -1971,66 +1998,43 @@ static void gizmo_3d_draw_invoke(wmGizmoGroup *gzgroup, wmGizmo *axis_active = ggd->gizmos[axis_idx_active]; const short axis_active_type = gizmo_get_axis_type(axis_idx_active); - if (axis_active_type == MAN_AXES_ROTATE) { - /* Hide other gizmos except the active one and #MAN_AXIS_ROT_C. - * #MAN_AXIS_ROT_C was displayed before and remains visible by convention. */ - gizmogroup_hide_all(ggd); - WM_gizmo_set_flag(axis_active, WM_GIZMO_HIDDEN, false); - WM_gizmo_set_flag(ggd->gizmos[MAN_AXIS_ROT_C], WM_GIZMO_HIDDEN, false); - } - else { - /* We switch from a modal gizmo to another. So make sure the gizmos are visible and have the - * default properties. */ - const int twtype_expected = (axis_active_type == MAN_AXES_TRANSLATE ? - V3D_GIZMO_SHOW_OBJECT_TRANSLATE : - V3D_GIZMO_SHOW_OBJECT_SCALE); + /* Display only the active gizmo. */ + gizmogroup_hide_all(ggd); + WM_gizmo_set_flag(axis_active, WM_GIZMO_HIDDEN, false); + gizmo_refresh_from_matrix(axis_active, axis_idx_active, ggd->twtype, rv3d->twmat, nullptr); - const int twtype = (ggd->twtype & twtype_expected) ? ggd->twtype : twtype_expected; - - float idot[3]; - gizmo_get_idot(rv3d, idot); - MAN_ITER_AXES_BEGIN (axis, axis_idx) { - const short axis_type = gizmo_get_axis_type(axis_idx); - if (gizmo_is_axis_visible(rv3d, twtype, idot, axis_type, axis_idx)) { - WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false); - gizmo_3d_setup_draw_default(axis, axis_idx); - gizmo_3d_setup_draw_from_twtype(axis, axis_idx, twtype); - } - else { - WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, true); - } - } - MAN_ITER_AXES_END; + if (ELEM(axis_idx_active, MAN_AXIS_TRANS_C, MAN_AXIS_SCALE_C, MAN_AXIS_ROT_C, MAN_AXIS_ROT_T)) { + WM_gizmo_set_matrix_rotation_from_z_axis(axis_active, rv3d->viewinv[2]); } - MAN_ITER_AXES_BEGIN (axis, axis_idx) { - if (axis->flag & WM_GIZMO_HIDDEN) { - continue; - } - gizmo_refresh_from_matrix(axis, axis_idx, ggd->twtype, rv3d->twmat, nullptr); + gizmo_3d_setup_draw_modal(axis_active, axis_idx_active, ggd->twtype); - if (ELEM(axis_idx, MAN_AXIS_TRANS_C, MAN_AXIS_SCALE_C, MAN_AXIS_ROT_C, MAN_AXIS_ROT_T)) { - WM_gizmo_set_matrix_rotation_from_z_axis(axis, rv3d->viewinv[2]); - } - - if (axis == axis_active) { - if (axis_active_type == MAN_AXES_ROTATE && axis_idx_active != MAN_AXIS_ROT_T) { - float mat[3][3]; - mul_m3_m4m4(mat, axis_active->matrix_basis, axis_active->matrix_offset); - gizmo_3d_dial_matrixbasis_calc( - region, mat[2], axis_active->matrix_basis[3], mval, axis_active->matrix_offset); - - copy_m3_m4(mat, axis_active->matrix_basis); - invert_m3(mat); - mul_m4_m3m4(axis_active->matrix_offset, mat, axis_active->matrix_offset); - zero_v3(axis_active->matrix_offset[3]); + if (axis_active_type == MAN_AXES_TRANSLATE) { + /* Arrows are used for visual reference, so keep all visible. */ + for (int axis_idx = MAN_AXIS_TRANS_X; axis_idx <= MAN_AXIS_TRANS_Z; axis_idx++) { + if (axis_idx == axis_idx_active) { + continue; } - - gizmo_3d_setup_draw_modal(axis_active, axis_idx); + wmGizmo *axis = ggd->gizmos[axis_idx]; + WM_gizmo_set_flag(axis, WM_GIZMO_HIDDEN, false); + gizmo_refresh_from_matrix(axis, axis_idx, ggd->twtype, rv3d->twmat, nullptr); + gizmo_3d_setup_draw_default(axis, axis_idx); + gizmo_3d_setup_draw_from_twtype(axis, axis_idx, ggd->twtype); + RNA_enum_set(axis->ptr, "draw_options", ED_GIZMO_ARROW_DRAW_FLAG_STEM); } } - MAN_ITER_AXES_END; + else if (axis_active_type == MAN_AXES_ROTATE && axis_idx_active != MAN_AXIS_ROT_T) { + float mat[3][3]; + mul_m3_m4m4(mat, axis_active->matrix_basis, axis_active->matrix_offset); + gizmo_3d_dial_matrixbasis_calc( + region, mat[2], axis_active->matrix_basis[3], mval, axis_active->matrix_offset); + + copy_m3_m4(mat, axis_active->matrix_basis); + invert_m3(mat); + mul_m4_m3m4(axis_active->matrix_offset, mat, axis_active->matrix_offset); + zero_v3(axis_active->matrix_offset[3]); + } } static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C,