Transform: improve visualization when dragging Gizmos #104624

Merged
Germano Cavalcante merged 1 commits from mano-wii/blender:xform_gizmo_v2 into main 2023-04-13 20:23:14 +02:00
7 changed files with 329 additions and 154 deletions

View File

@ -7,6 +7,8 @@
#pragma once
#define DIAL_RESOLUTION 48
/**
* Data for common interactions. Used in gizmo_library_utils.c functions.
*/

View File

@ -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[] = {

View File

@ -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

View File

@ -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) {

View File

@ -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)

View File

@ -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,
};
/* -------------------------------------------------------------------- */

View File

@ -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,