Gizmo: add depth bias for 3D selection
This allows some gizmos priority over others even when they're behind.
This commit is contained in:
@@ -384,6 +384,7 @@ static void rna_Gizmo_matrix_world_get(PointerRNA *ptr, float value[16])
|
||||
|
||||
RNA_GIZMO_GENERIC_FLOAT_RW_DEF(scale_basis, scale_basis);
|
||||
RNA_GIZMO_GENERIC_FLOAT_RW_DEF(line_width, line_width);
|
||||
RNA_GIZMO_GENERIC_FLOAT_RW_DEF(select_bias, select_bias);
|
||||
|
||||
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_draw_hover, flag, WM_GIZMO_DRAW_HOVER);
|
||||
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_draw_modal, flag, WM_GIZMO_DRAW_MODAL);
|
||||
@@ -1159,6 +1160,12 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
||||
RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "select_bias", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Select Bias", "Depth bias used for selection");
|
||||
RNA_def_property_float_funcs(
|
||||
prop, "rna_Gizmo_select_bias_get", "rna_Gizmo_select_bias_set", NULL);
|
||||
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||
|
||||
/* wmGizmo.flag */
|
||||
/* WM_GIZMO_HIDDEN */
|
||||
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
|
||||
|
||||
@@ -198,6 +198,10 @@ struct wmGizmo {
|
||||
/** For single click button gizmos, use a different part as a fallback, -1 when unused. */
|
||||
int drag_part;
|
||||
|
||||
/** Distance to bias this gizmo above others when picking
|
||||
* (in worldspace, scaled by the gizmo scale - when used). */
|
||||
float select_bias;
|
||||
|
||||
/**
|
||||
* Transformation of the gizmo in 2d or 3d space.
|
||||
* - Matrix axis are expected to be unit length (scale is applied after).
|
||||
|
||||
@@ -25,8 +25,10 @@
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_bits.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_array.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
@@ -470,7 +472,8 @@ void WM_gizmomap_draw(wmGizmoMap *gzmap,
|
||||
|
||||
static void gizmo_draw_select_3D_loop(const bContext *C,
|
||||
ListBase *visible_gizmos,
|
||||
const wmGizmo *gz_stop)
|
||||
const wmGizmo *gz_stop,
|
||||
bool *r_use_select_bias)
|
||||
{
|
||||
int select_id = 0;
|
||||
wmGizmo *gz;
|
||||
@@ -511,6 +514,10 @@ static void gizmo_draw_select_3D_loop(const bContext *C,
|
||||
is_depth_skip_prev = is_depth_skip;
|
||||
}
|
||||
|
||||
if (gz->select_bias != 0.0) {
|
||||
*r_use_select_bias = true;
|
||||
}
|
||||
|
||||
/* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */
|
||||
|
||||
gz->type->draw_select(C, gz, select_id << 8);
|
||||
@@ -543,24 +550,68 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos,
|
||||
ED_view3d_draw_setup_view(
|
||||
CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, v3d, NULL, NULL, &rect);
|
||||
|
||||
bool use_select_bias = false;
|
||||
|
||||
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
|
||||
/* do the drawing */
|
||||
gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop);
|
||||
gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop, &use_select_bias);
|
||||
|
||||
hits = GPU_select_end();
|
||||
|
||||
if (hits > 0) {
|
||||
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
|
||||
gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop);
|
||||
gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop, &use_select_bias);
|
||||
GPU_select_end();
|
||||
}
|
||||
|
||||
ED_view3d_draw_setup_view(
|
||||
CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, v3d, NULL, NULL, NULL);
|
||||
|
||||
const GLuint *hit_near = GPU_select_buffer_near(buffer, hits);
|
||||
if (use_select_bias && (hits > 1)) {
|
||||
wmGizmo **gizmo_table = NULL;
|
||||
BLI_array_staticdeclare(gizmo_table, 1024);
|
||||
for (LinkData *link = visible_gizmos->first; link; link = link->next) {
|
||||
BLI_array_append(gizmo_table, link->data);
|
||||
}
|
||||
float co_direction[3];
|
||||
float co_screen[3] = {co[0], co[1], 0.0f};
|
||||
ED_view3d_win_to_vector(ar, (float[2]){UNPACK2(co)}, co_direction);
|
||||
|
||||
return hit_near ? hit_near[3] : -1;
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
const int viewport[4] = {0, 0, ar->winx, ar->winy};
|
||||
float co_3d_origin[3];
|
||||
|
||||
GPU_matrix_unproject_model_inverted(
|
||||
co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
|
||||
|
||||
GLuint *buf_iter = buffer;
|
||||
int hit_found = -1;
|
||||
float dot_best = FLT_MAX;
|
||||
|
||||
for (int i = 0; i < hits; i++, buf_iter += 4) {
|
||||
BLI_assert(buf_iter[3] != -1);
|
||||
wmGizmo *gz = gizmo_table[buf_iter[3] >> 8];
|
||||
float co_3d[3];
|
||||
co_screen[2] = int_as_float(buf_iter[1]);
|
||||
GPU_matrix_unproject_model_inverted(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
|
||||
float select_bias = gz->select_bias;
|
||||
if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
|
||||
select_bias *= gz->scale_final;
|
||||
}
|
||||
sub_v3_v3(co_3d, co_3d_origin);
|
||||
const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
|
||||
if (dot_best > dot_test) {
|
||||
dot_best = dot_test;
|
||||
hit_found = buf_iter[3];
|
||||
}
|
||||
}
|
||||
BLI_array_free(gizmo_table);
|
||||
return hit_found;
|
||||
}
|
||||
else {
|
||||
const GLuint *hit_near = GPU_select_buffer_near(buffer, hits);
|
||||
return hit_near ? hit_near[3] : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user