UI: Viewport Navigate Gizmo Refactor

Simplification and changes to the Navigation gizmo. Better indication of negative axes, consistent use of color and size to indicate orientation, ability to be resized.

Differential Revision: https://developer.blender.org/D9744

Reviewed by Campbell Barton
This commit is contained in:
Harley Acheson 2021-01-23 13:10:07 -08:00
parent aaa1d58054
commit ded9484925
Notes: blender-bot 2023-02-14 11:24:03 +01:00
Referenced by issue #84099, Blender crashes then corrupts blend file macOS
9 changed files with 253 additions and 431 deletions

View File

@ -131,6 +131,7 @@ const UserDef U_default = {
.prefetchframes = 0,
.pad_rot_angle = 15,
.gizmo_size_navigate_v3d = 80,
.rvisize = 25,
.rvibright = 8,
.recent_files = 10,

View File

@ -691,6 +691,9 @@ class USERPREF_PT_viewport_display(ViewportPanel, CenterAlignMixIn, Panel):
col.prop(view, "mini_axis_size", text="Size")
col.prop(view, "mini_axis_brightness", text="Brightness")
if view.mini_axis_type == 'GIZMO':
col.prop(view, "gizmo_size_navigate_v3d", text="Size")
class USERPREF_PT_viewport_quality(ViewportPanel, CenterAlignMixIn, Panel):
bl_label = "Quality"

View File

@ -844,6 +844,9 @@ void blo_do_versions_userdef(UserDef *userdef)
*/
{
/* Keep this block, even when empty. */
if (userdef->gizmo_size_navigate_v3d == 0) {
userdef->gizmo_size_navigate_v3d = 80;
}
}
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {

View File

@ -443,6 +443,16 @@ void UI_draw_roundbox_shade_x(bool filled,
float shadetop,
float shadedown,
const float col[4]);
void UI_draw_roundbox_4fv_ex(float minx,
float miny,
float maxx,
float maxy,
const float inner1[4],
const float inner2[4],
float shade_dir,
float outline[4],
float outline_width,
float rad);
#if 0 /* unused */
int UI_draw_roundbox_corner_get(void);

View File

@ -81,6 +81,57 @@ int UI_draw_roundbox_corner_get(void)
}
#endif
void UI_draw_roundbox_4fv_ex(float minx,
float miny,
float maxx,
float maxy,
const float inner1[4],
const float inner2[4],
float shade_dir,
float outline[4],
float outline_width,
float rad)
{
/* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
* If it has been scaled, then it's no longer valid. */
uiWidgetBaseParameters widget_params = {
.recti.xmin = minx + outline_width,
.recti.ymin = miny + outline_width,
.recti.xmax = maxx - outline_width,
.recti.ymax = maxy - outline_width,
.rect.xmin = minx,
.rect.ymin = miny,
.rect.xmax = maxx,
.rect.ymax = maxy,
.radi = rad,
.rad = rad,
.round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f,
.round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f,
.round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f,
.round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f,
.color_inner1[0] = inner1 ? inner1[0] : 0.0f,
.color_inner1[1] = inner1 ? inner1[1] : 0.0f,
.color_inner1[2] = inner1 ? inner1[2] : 0.0f,
.color_inner1[3] = inner1 ? inner1[3] : 0.0f,
.color_inner2[0] = inner2 ? inner2[0] : inner1 ? inner1[0] : 0.0f,
.color_inner2[1] = inner2 ? inner2[1] : inner1 ? inner1[1] : 0.0f,
.color_inner2[2] = inner2 ? inner2[2] : inner1 ? inner1[2] : 0.0f,
.color_inner2[3] = inner2 ? inner2[3] : inner1 ? inner1[3] : 0.0f,
.color_outline[0] = outline ? outline[0] : inner1 ? inner1[0] : 0.0f,
.color_outline[1] = outline ? outline[1] : inner1 ? inner1[1] : 0.0f,
.color_outline[2] = outline ? outline[2] : inner1 ? inner1[2] : 0.0f,
.color_outline[3] = outline ? outline[3] : inner1 ? inner1[3] : 0.0f,
.shade_dir = shade_dir,
.alpha_discard = 1.0f,
};
GPUBatch *batch = ui_batch_roundbox_widget_get();
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE);
GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params);
GPU_blend(GPU_BLEND_ALPHA);
GPU_batch_draw(batch);
GPU_blend(GPU_BLEND_NONE);
}
void UI_draw_roundbox_3ub_alpha(bool filled,
float minx,
float miny,

View File

@ -45,14 +45,17 @@
/** \name View3D Navigation Gizmo Group
* \{ */
/* Offset from screen edge. */
#define GIZMO_OFFSET_FAC 1.2f
/* Size of main icon. */
#define GIZMO_SIZE 80
/* Factor for size of smaller button. */
#define GIZMO_MINI_FAC 0.35f
/* How much mini buttons offset from the primary. */
#define GIZMO_MINI_OFFSET_FAC 0.38f
#define GIZMO_SIZE U.gizmo_size_navigate_v3d
/* Main gizmo offset from screen edges in unscaled pixels. */
#define GIZMO_OFFSET 10.0f
/* Width of smaller buttons in unscaled pixels. */
#define GIZMO_MINI_SIZE 28.0f
/* Margin around the smaller buttons. */
#define GIZMO_MINI_OFFSET 2.0f
enum {
GZ_INDEX_MOVE = 0,
@ -174,7 +177,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
}
/* may be overwritten later */
gz->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2;
gz->scale_basis = GIZMO_MINI_SIZE / 2.0f;
if (info->icon != 0) {
PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon");
RNA_property_enum_set(gz->ptr, prop, info->icon);
@ -212,7 +215,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE];
gz->scale_basis = GIZMO_SIZE / 2;
gz->scale_basis = GIZMO_SIZE / 2.0f;
const char mapping[6] = {
RV3D_VIEW_LEFT,
RV3D_VIEW_RIGHT,
@ -263,9 +266,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0;
const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO);
const float icon_size = GIZMO_SIZE;
const float icon_offset = (icon_size * 0.52f) * GIZMO_OFFSET_FAC * UI_DPI_FAC;
const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC;
const float icon_offset = ((GIZMO_SIZE / 2.0f) + GIZMO_OFFSET) * UI_DPI_FAC;
const float icon_offset_mini = (GIZMO_MINI_SIZE + GIZMO_MINI_OFFSET) * UI_DPI_FAC;
const float co_rotate[2] = {
rect_visible->xmax - icon_offset,
rect_visible->ymax - icon_offset,

View File

@ -40,6 +40,8 @@
#include "GPU_matrix.h"
#include "GPU_state.h"
#include "BLF_api.h"
#include "RNA_access.h"
#include "RNA_define.h"
@ -53,169 +55,34 @@
#include "view3d_intern.h"
#define USE_AXIS_FONT
#define USE_FADE_BACKGROUND
/* Radius of the entire background. */
#define WIDGET_RADIUS ((U.gizmo_size_navigate_v3d / 2.0f) * UI_DPI_FAC)
#ifdef USE_AXIS_FONT
# include "BLF_api.h"
#endif
/* Sizes of axis spheres containing XYZ characters in relation to above. */
#define AXIS_HANDLE_SIZE 0.20f
#define DIAL_RESOLUTION 32
#define AXIS_LINE_WIDTH ((U.gizmo_size_navigate_v3d / 40.0f) * U.pixelsize)
#define AXIS_RING_WIDTH ((U.gizmo_size_navigate_v3d / 60.0f) * U.pixelsize)
#define AXIS_TEXT_SIZE (WIDGET_RADIUS * AXIS_HANDLE_SIZE * 1.25f)
/* Sizes of axis spheres containing XYZ characters. */
#define AXIS_HANDLE_SIZE_FG 0.19f
/* When pointing away from the view. */
#define AXIS_HANDLE_SIZE_BG 0.15f
/* How far axis handles are away from the center. */
#define AXIS_HANDLE_OFFSET (1.0f - AXIS_HANDLE_SIZE_FG)
/* distance within this from center is considered positive. */
#define AXIS_DEPTH_BIAS 0.01f
struct AxisDrawInfo {
/* Matrix is needed for screen-aligned font drawing. */
#ifdef USE_AXIS_FONT
float matrix_final[4][4];
#endif
#ifdef USE_FADE_BACKGROUND
float color_bg[3];
#endif
};
#ifndef USE_AXIS_FONT
/**
* \param viewmat_local_unit: is typically the 'rv3d->viewmatob'
* copied into a 3x3 matrix and normalized.
*/
static void draw_xyz_wire(
uint pos_id, const float viewmat_local_unit[3][3], const float c[3], float size, int axis)
static void gizmo_axis_draw(const bContext *C, wmGizmo *gz)
{
int line_type;
float buffer[4][3];
int n = 0;
float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f};
float dim = size * 0.1f;
float dx[3], dy[3];
dx[0] = dim;
dx[1] = 0.0f;
dx[2] = 0.0f;
dy[0] = 0.0f;
dy[1] = dim;
dy[2] = 0.0f;
switch (axis) {
case 0: /* x axis */
line_type = GPU_PRIM_LINES;
/* bottom left to top right */
negate_v3_v3(v1, dx);
sub_v3_v3(v1, dy);
copy_v3_v3(v2, dx);
add_v3_v3(v2, dy);
copy_v3_v3(buffer[n++], v1);
copy_v3_v3(buffer[n++], v2);
/* top left to bottom right */
mul_v3_fl(dy, 2.0f);
add_v3_v3(v1, dy);
sub_v3_v3(v2, dy);
copy_v3_v3(buffer[n++], v1);
copy_v3_v3(buffer[n++], v2);
break;
case 1: /* y axis */
line_type = GPU_PRIM_LINES;
/* bottom left to top right */
mul_v3_fl(dx, 0.75f);
negate_v3_v3(v1, dx);
sub_v3_v3(v1, dy);
copy_v3_v3(v2, dx);
add_v3_v3(v2, dy);
copy_v3_v3(buffer[n++], v1);
copy_v3_v3(buffer[n++], v2);
/* top left to center */
mul_v3_fl(dy, 2.0f);
add_v3_v3(v1, dy);
zero_v3(v2);
copy_v3_v3(buffer[n++], v1);
copy_v3_v3(buffer[n++], v2);
break;
case 2: /* z axis */
line_type = GPU_PRIM_LINE_STRIP;
/* start at top left */
negate_v3_v3(v1, dx);
add_v3_v3(v1, dy);
copy_v3_v3(buffer[n++], v1);
mul_v3_fl(dx, 2.0f);
add_v3_v3(v1, dx);
copy_v3_v3(buffer[n++], v1);
mul_v3_fl(dy, 2.0f);
sub_v3_v3(v1, dx);
sub_v3_v3(v1, dy);
copy_v3_v3(buffer[n++], v1);
add_v3_v3(v1, dx);
copy_v3_v3(buffer[n++], v1);
break;
default:
BLI_assert(0);
return;
}
for (int i = 0; i < n; i++) {
mul_transposed_m3_v3((float(*)[3])viewmat_local_unit, buffer[i]);
add_v3_v3(buffer[i], c);
}
immBegin(line_type, n);
for (int i = 0; i < n; i++) {
immVertex3fv(pos_id, buffer[i]);
}
immEnd();
}
#endif /* !USE_AXIS_FONT */
/**
* \param draw_info: Extra data needed for drawing.
*/
static void axis_geom_draw(const wmGizmo *gz,
const float color[4],
const bool select,
const struct AxisDrawInfo *draw_info)
{
float viewport[4];
GPU_viewport_size_get_f(viewport);
GPUVertFormat *format = immVertexFormat();
const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
struct {
float depth;
char index;
char axis;
char axis_opposite;
bool is_pos;
} axis_order[6] = {
{-gz->matrix_offset[0][2], 0, 0, false},
{+gz->matrix_offset[0][2], 1, 0, true},
{-gz->matrix_offset[1][2], 2, 1, false},
{+gz->matrix_offset[1][2], 3, 1, true},
{-gz->matrix_offset[2][2], 4, 2, false},
{+gz->matrix_offset[2][2], 5, 2, true},
{-gz->matrix_offset[0][2], 0, 0, 1, false},
{+gz->matrix_offset[0][2], 1, 0, 0, true},
{-gz->matrix_offset[1][2], 2, 1, 3, false},
{+gz->matrix_offset[1][2], 3, 1, 2, true},
{-gz->matrix_offset[2][2], 4, 2, 5, false},
{+gz->matrix_offset[2][2], 5, 2, 4, true},
};
int axis_align = -1;
@ -226,25 +93,35 @@ static void axis_geom_draw(const wmGizmo *gz,
}
}
/* Show backwards pointing highlight on-top (else we can't see it at all). */
if ((select == false) && (gz->highlight_part > 0) && (axis_align != -1)) {
if (axis_order[gz->highlight_part - 1].is_pos == false) {
axis_order[gz->highlight_part - 1].depth = FLT_MAX;
}
}
qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
static const float axis_highlight[4] = {1, 1, 1, 1};
static const float axis_black[4] = {0, 0, 0, 1};
/* When the cursor is over any of the gizmos (show circle backdrop). */
const bool is_active = ((gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0);
/* Background color of the View3D, used to mix colors. */
float view_color[4];
ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), view_color);
view_color[3] = 1.0f;
float matrix_screen[4][4];
float matrix_unit[4][4];
unit_m4(matrix_unit);
WM_gizmo_calc_matrix_final_params(gz,
&((struct WM_GizmoMatrixParams){
.matrix_offset = matrix_unit,
}),
matrix_screen);
GPU_matrix_push();
GPU_matrix_mul(matrix_screen);
GPUVertFormat *format = immVertexFormat();
const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
static float axis_color[3][4];
const float axis_depth_bias = 0.01f;
const float sphere_scale = 1.15f;
/* TODO(fclem): Is there a way to get the widget radius? */
const float widget_pix_size = 40.0f * U.dpi_fac;
#ifdef USE_AXIS_FONT
struct {
float matrix[4][4];
float matrix_m3[3][3];
@ -252,38 +129,29 @@ static void axis_geom_draw(const wmGizmo *gz,
int id;
} font;
if (select == false) {
font.id = blf_mono_font;
BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP);
BLF_color4fv(font.id, axis_black);
BLF_size(font.id, 12 * U.dpi_fac, 72);
font.id = BLF_default();
BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP);
BLF_enable(font.id, BLF_BOLD);
BLF_size(font.id, AXIS_TEXT_SIZE, 72);
BLF_position(font.id, 0, 0, 0);
/* The view matrix is used to position the text. */
BLF_position(font.id, 0, 0, 0);
/* Calculate the inverse of the (matrix_final * matrix_offset).
* This allows us to use the final location, while reversing the rotation so fonts
* show without any rotation. */
float m3[3][3];
float m3_offset[3][3];
copy_m3_m4(m3, matrix_screen);
copy_m3_m4(m3_offset, gz->matrix_offset);
mul_m3_m3m3(m3, m3, m3_offset);
copy_m3_m3(font.matrix_m3_invert, m3);
invert_m3(m3);
copy_m3_m3(font.matrix_m3, m3);
copy_m4_m3(font.matrix, m3);
/* Calculate the inverse of the (matrix_final * matrix_offset).
* This allows us to use the final location, while reversing the rotation so fonts
* show without any rotation. */
float m3[3][3];
float m3_offset[3][3];
copy_m3_m4(m3, draw_info->matrix_final);
copy_m3_m4(m3_offset, gz->matrix_offset);
mul_m3_m3m3(m3, m3, m3_offset);
copy_m3_m3(font.matrix_m3_invert, m3);
invert_m3(m3);
copy_m3_m3(font.matrix_m3, m3);
copy_m4_m3(font.matrix, m3);
}
#endif
/* When the cursor is over any of the gizmos (show circle backdrop). */
const bool is_active = (color[3] != 0.0f);
const float clip_range = gz->scale_final * sphere_scale;
bool use_project_matrix = (clip_range >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT);
bool use_project_matrix = (gz->scale_final >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT);
if (use_project_matrix) {
GPU_matrix_push_projection();
GPU_matrix_ortho_set_z(-clip_range, clip_range);
GPU_matrix_ortho_set_z(-gz->scale_final, gz->scale_final);
}
UI_draw_roundbox_corner_set(UI_CNR_ALL);
@ -291,263 +159,143 @@ static void axis_geom_draw(const wmGizmo *gz,
/* Circle defining active area. */
if (is_active) {
immUnbindProgram();
float rad = widget_pix_size;
const float rad = WIDGET_RADIUS;
GPU_matrix_push();
GPU_matrix_scale_1f(1.0f / rad);
UI_draw_roundbox_4fv(true, -rad, -rad, rad, rad, rad, color);
UI_draw_roundbox_4fv(true, -rad, -rad, rad, rad, rad, gz->color_hi);
GPU_matrix_pop();
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
}
GPU_matrix_push();
GPU_matrix_mul(gz->matrix_offset);
for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) {
const int index = axis_order[axis_index].index;
const int axis = axis_order[axis_index].axis;
const bool is_pos = axis_order[axis_index].is_pos;
const bool is_highlight = index + 1 == gz->highlight_part;
const float depth = axis_order[axis_index].depth;
const bool is_behind = (depth <= (AXIS_DEPTH_BIAS * (is_pos ? -1 : 1)));
bool is_aligned_front = (axis_align != -1 && axis_align == axis && !is_behind);
bool is_aligned_back = (axis_align != -1 && axis_align == axis && is_behind);
const float v[3] = {0, 0, (1.0f - AXIS_HANDLE_SIZE) * (is_pos ? 1 : -1)};
const float v_final[3] = {v[(axis + 2) % 3], v[(axis + 1) % 3], v[axis]};
bool is_highlight = index + 1 == gz->highlight_part;
/* Check if highlight part is the other side when axis aligned. */
if (is_aligned_front && (axis_order[axis_index].axis_opposite + 1 == gz->highlight_part)) {
is_highlight = true;
}
UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]);
axis_color[axis][3] = 1.0f;
const int index_z = axis;
const int index_y = (axis + 1) % 3;
const int index_x = (axis + 2) % 3;
/* Color that is full at front, but 50% view background when in back. */
float fading_color[4];
interp_v4_v4v4(fading_color, view_color, axis_color[axis], ((depth + 1) * 0.25) + 0.5);
bool ok = true;
/* Color that is midway between front and back. */
float middle_color[4];
interp_v4_v4v4(middle_color, view_color, axis_color[axis], 0.75f);
/* Skip view align axis when selecting (allows to switch to opposite side). */
if (select && ((axis_align == axis) && (gz->matrix_offset[axis][2] > 0.0f) == is_pos)) {
ok = false;
GPU_blend(GPU_BLEND_ALPHA);
/* Axis Line. */
if (is_pos || axis_align != -1) {
/* Extend slightly to meet better at the center. */
float v_start[3] = {0.0f, 0.0f, 0.0f};
mul_v3_v3fl(v_start, v_final, -(AXIS_LINE_WIDTH / WIDGET_RADIUS * 0.66f));
/* Decrease length of line by ball radius. */
float v_end[3] = {0.0f, 0.0f, 0.0f};
mul_v3_v3fl(v_end, v_final, 1.0f - AXIS_HANDLE_SIZE);
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR);
immUniform2fv("viewportSize", &viewport_size[2]);
immUniform1f("lineWidth", AXIS_LINE_WIDTH);
immBegin(GPU_PRIM_LINES, 2);
immAttr4fv(color_id, middle_color);
immVertex3fv(pos_id, v_start);
immAttr4fv(color_id, fading_color);
immVertex3fv(pos_id, v_end);
immEnd();
immUnbindProgram();
}
if (ok) {
/* Check aligned, since the front axis won't display in this case,
* and we want to make sure all 3 axes have a character at all times. */
const bool show_axis_char = (is_pos || (axis == axis_align));
const float v[3] = {0, 0, AXIS_HANDLE_OFFSET * (is_pos ? 1 : -1)};
const float v_final[3] = {v[index_x], v[index_y], v[index_z]};
const float *color_current = is_highlight ? axis_highlight : axis_color[axis];
float color_current_fade[4];
/* Flip the faded state when axis aligned, since we're hiding the front-mode axis
* otherwise we see the color for the back-most axis, which is useful for
* click-to-rotate 180d but not useful to visualize.
*
* Use depth bias so axis-aligned views show the positive axis as being in-front.
* This is a detail so primary axes show as dominant.
*/
const bool is_pos_color = (axis_order[axis_index].depth >
(axis_depth_bias * (is_pos ? -1 : 1)));
if (select == false) {
#ifdef USE_FADE_BACKGROUND
interp_v3_v3v3(
color_current_fade, draw_info->color_bg, color_current, is_highlight ? 1.0 : 0.5f);
color_current_fade[3] = color_current[3];
#else
copy_v4_v4(color_current_fade, color_current);
color_current_fade[3] *= 0.2;
#endif
}
else {
copy_v4_fl(color_current_fade, 1.0f);
}
/* Axis Line. */
if (is_pos) {
float v_start[3];
immUnbindProgram();
GPU_blend(GPU_BLEND_ALPHA);
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniform2fv("viewportSize", &viewport[2]);
immUniform1f("lineWidth", 2.0f * U.pixelsize);
immUniformColor4fv(is_pos_color ? color_current : color_current_fade);
immBegin(GPU_PRIM_LINES, 2);
if (axis_align == -1) {
zero_v3(v_start);
/* Axis Ball. */
if (!is_aligned_back) {
float *inner_color = fading_color;
float *outline_color = fading_color;
if (!is_pos) {
float negative_color[4];
if (is_aligned_front) {
inner_color = fading_color;
interp_v4_v4v4(
negative_color, (float[4]){1.0f, 1.0f, 1.0f, 1.0f}, axis_color[axis], 0.5f);
negative_color[3] = MIN2(depth + 1, 1.0f);
outline_color = negative_color;
}
else {
/* When axis aligned we don't draw the front most axis
* (allowing us to switch to the opposite side).
* In this case don't draw lines over axis pointing away from us
* because it obscures character and looks noisy.
*/
mul_v3_v3fl(v_start, v_final, 0.3f);
outline_color = fading_color;
interp_v4_v4v4(negative_color, view_color, axis_color[axis], 0.25f);
negative_color[3] = MIN2(depth + 1, 1.0f);
inner_color = negative_color;
}
immVertex3fv(pos_id, v_start);
immVertex3fv(pos_id, v_final);
immEnd();
immUnbindProgram();
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
}
/* Axis Ball. */
#ifdef USE_AXIS_FONT
if (select == false) {
immUnbindProgram();
GPU_matrix_push();
GPU_matrix_translate_3fv(v_final);
GPU_matrix_mul(font.matrix);
/* Size change from back to front: 0.92f - 1.08f. */
float scale = ((depth + 1) * 0.08f) + 0.92f;
const float rad = WIDGET_RADIUS * AXIS_HANDLE_SIZE * scale;
UI_draw_roundbox_4fv_ex(
-rad, -rad, rad, rad, inner_color, NULL, 0.0f, outline_color, AXIS_RING_WIDTH, rad);
GPU_matrix_pop();
}
GPU_matrix_push();
GPU_matrix_translate_3fv(v_final);
GPU_matrix_mul(font.matrix);
float rad = widget_pix_size * (is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG);
/* Black outlines for negative axis balls, otherwise they can be hard to see since
* they use a faded color which can be similar to the circle backdrop in tone. */
if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) {
static const float axis_black_faded[4] = {0.0f, 0.0f, 0.0f, 0.2f};
float outline = rad * sphere_scale;
UI_draw_roundbox_4fv(
true, -outline, -outline, outline, outline, outline, axis_black_faded);
}
const float *col = is_pos_color ? color_current : color_current_fade;
UI_draw_roundbox_4fv(true, -rad, -rad, rad, rad, rad, col);
GPU_matrix_pop();
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
/* Axis XYZ Character. */
if ((is_pos || is_highlight || (axis == axis_align)) && !is_aligned_back) {
float axis_str_width, axis_string_height;
char axis_str[3] = {'X' + axis, 0, 0};
if (!is_pos) {
axis_str[0] = '-';
axis_str[1] = 'X' + axis;
}
else
#endif
{
GPU_matrix_push();
GPU_matrix_translate_3fv(v_final);
GPU_matrix_scale_1f(is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG);
BLF_width_and_height(font.id, axis_str, 3, &axis_str_width, &axis_string_height);
GPUBatch *sphere = GPU_batch_preset_sphere(0);
GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
/* Black outlines for negative axis balls, otherwise they can be hard to see since
* they use a faded color which can be similar to the circle backdrop in tone. */
if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) {
static const float axis_black_faded[4] = {0, 0, 0, 0.2f};
GPU_matrix_scale_1f(sphere_scale);
GPU_batch_uniform_4fv(sphere, "color", axis_black_faded);
GPU_batch_draw(sphere);
GPU_matrix_scale_1f(1.0 / sphere_scale);
}
GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
GPU_batch_uniform_4fv(sphere, "color", is_pos_color ? color_current : color_current_fade);
GPU_batch_draw(sphere);
GPU_matrix_pop();
}
/* Axis XYZ Character. */
if (show_axis_char && (select == false)) {
#ifdef USE_AXIS_FONT
float axis_str_size[2] = {0};
const char axis_str[2] = {'X' + axis, 0};
BLF_width_and_height(font.id, axis_str, 2, &axis_str_size[0], &axis_str_size[1]);
/* Calculate pixel aligned location, without this text draws fuzzy. */
float v_final_px[3];
mul_v3_m3v3(v_final_px, font.matrix_m3_invert, v_final);
/* Center the test and pixel align, it's important to round once
* otherwise the characters are noticeably not-centered.
* If this wasn't an issue we could use #BLF_position to place the text. */
v_final_px[0] = roundf(v_final_px[0] - (axis_str_size[0] / 2.0f));
v_final_px[1] = roundf(v_final_px[1] - (axis_str_size[1] / 2.0f));
mul_m3_v3(font.matrix_m3, v_final_px);
immUnbindProgram();
GPU_matrix_push();
GPU_matrix_translate_3fv(v_final_px);
GPU_matrix_mul(font.matrix);
BLF_draw_ascii(font.id, axis_str, 2);
GPU_blend(GPU_BLEND_ALPHA); /* XXX, blf disables */
GPU_matrix_pop();
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
#else
immUnbindProgram();
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
GPU_line_width(1.0f);
float m3[3][3];
copy_m3_m4(m3, gz->matrix_offset);
immUniformColor4fv(axis_black);
draw_xyz_wire(pos_id, m3, v_final, 1.0, axis);
immUnbindProgram();
#endif
/* Calculate pixel-aligned location, without this text draws fuzzy. */
float v_final_px[3];
mul_v3_m3v3(v_final_px, font.matrix_m3_invert, v_final);
/* Center the text and pixel align, it's important to round once
* otherwise the characters are noticeably not-centered.
* If this wasn't an issue we could use #BLF_position to place the text. */
v_final_px[0] = roundf(v_final_px[0] - (axis_str_width * (is_pos ? 0.5f : 0.55f)));
v_final_px[1] = roundf(v_final_px[1] - (axis_string_height / 2.0f));
mul_m3_v3(font.matrix_m3, v_final_px);
GPU_matrix_push();
GPU_matrix_translate_3fv(v_final_px);
GPU_matrix_mul(font.matrix);
float text_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
if (!is_highlight) {
zero_v4(text_color);
text_color[3] = is_active ? 1.0f : 0.9f;
}
BLF_color4fv(font.id, text_color);
BLF_draw_ascii(font.id, axis_str, 2);
GPU_matrix_pop();
}
}
GPU_matrix_pop();
immUnbindProgram();
if (use_project_matrix) {
GPU_matrix_pop_projection();
}
}
static void axis3d_draw_intern(const bContext *C,
wmGizmo *gz,
const bool select,
const bool highlight)
{
const float *color = highlight ? gz->color_hi : gz->color;
float matrix_final[4][4];
float matrix_unit[4][4];
unit_m4(matrix_unit);
WM_gizmo_calc_matrix_final_params(gz,
&((struct WM_GizmoMatrixParams){
.matrix_offset = matrix_unit,
}),
matrix_final);
GPU_matrix_push();
GPU_matrix_mul(matrix_final);
struct AxisDrawInfo draw_info;
#ifdef USE_AXIS_FONT
if (select == false) {
copy_m4_m4(draw_info.matrix_final, matrix_final);
}
#endif
#ifdef USE_FADE_BACKGROUND
if (select == false) {
ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), draw_info.color_bg);
}
#else
UNUSED_VARS(C);
#endif
GPU_blend(GPU_BLEND_ALPHA);
axis_geom_draw(gz, color, select, &draw_info);
GPU_blend(GPU_BLEND_NONE);
BLF_disable(font.id, BLF_BOLD);
GPU_matrix_pop();
}
static void gizmo_axis_draw(const bContext *C, wmGizmo *gz)
{
const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL;
const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0;
(void)is_modal;
GPU_blend(GPU_BLEND_ALPHA);
axis3d_draw_intern(C, gz, false, is_highlight);
GPU_blend(GPU_BLEND_NONE);
}
static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
{
float point_local[2] = {UNPACK2(mval)};
@ -601,12 +349,9 @@ static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mv
return -1;
}
static int gizmo_axis_cursor_get(wmGizmo *gz)
static int gizmo_axis_cursor_get(wmGizmo *UNUSED(gz))
{
if (gz->highlight_part > 0) {
return WM_CURSOR_EDIT;
}
return WM_CURSOR_NSEW_SCROLL;
return WM_CURSOR_DEFAULT;
}
void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt)

View File

@ -773,7 +773,9 @@ typedef struct UserDef {
int prefetchframes;
/** Control the rotation step of the view when PAD2, PAD4, PAD6&PAD8 is use. */
float pad_rot_angle;
char _pad12[4];
/** Navigate gizmo size. */
char gizmo_size_navigate_v3d;
char _pad12[3];
/** Rotating view icon size. */
short rvisize;
/** Rotating view icon brightness. */

View File

@ -4720,6 +4720,11 @@ static void rna_def_userdef_view(BlenderRNA *brna)
"Show a small rotating 3D axes in the top right corner of the 3D View");
RNA_def_property_update(prop, 0, "rna_userdef_gizmo_update");
prop = RNA_def_property(srna, "gizmo_size_navigate_v3d", PROP_INT, PROP_PIXEL);
RNA_def_property_range(prop, 30, 200);
RNA_def_property_ui_text(prop, "Navigate Gizmo Size", "The Navigate Gizmo size");
RNA_def_property_update(prop, 0, "rna_userdef_gizmo_update");
prop = RNA_def_property(srna, "mini_axis_size", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "rvisize");
RNA_def_property_range(prop, 10, 64);