Gizmo: support for 2D selection checks for 3D gizmos

This means 3D manipulators can use their own logic
for checking if the cursor intersects.
This commit is contained in:
2018-08-10 17:32:40 +10:00
parent 3daf5cc1ce
commit e18a2c4ed7
2 changed files with 55 additions and 30 deletions

View File

@@ -169,7 +169,7 @@ void wm_gizmogroup_intersectable_gizmos_to_list(const wmGizmoGroup *gzgroup, Lis
{ {
for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) { for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
if ((gz->flag & WM_GIZMO_HIDDEN) == 0) { if ((gz->flag & WM_GIZMO_HIDDEN) == 0) {
if (((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) && gz->type->draw_select) || if (((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) && (gz->type->draw_select || gz->type->test_select)) ||
((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0 && gz->type->test_select)) ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0 && gz->type->test_select))
{ {
BLI_addhead(listbase, BLI_genericNodeN(gz)); BLI_addhead(listbase, BLI_genericNodeN(gz));

View File

@@ -453,7 +453,9 @@ void WM_gizmomap_draw(
BLI_assert(BLI_listbase_is_empty(&draw_gizmos)); BLI_assert(BLI_listbase_is_empty(&draw_gizmos));
} }
static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmos) static void gizmo_draw_select_3D_loop(
const bContext *C, ListBase *visible_gizmos,
const wmGizmo *gz_stop)
{ {
int select_id = 0; int select_id = 0;
wmGizmo *gz; wmGizmo *gz;
@@ -462,8 +464,14 @@ static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmo
bool is_depth_prev = false; bool is_depth_prev = false;
bool is_depth_skip_prev = false; bool is_depth_skip_prev = false;
for (LinkData *link = visible_gizmos->first; link; link = link->next) { for (LinkData *link = visible_gizmos->first; link; link = link->next, select_id++) {
gz = link->data; gz = link->data;
if (gz == gz_stop) {
break;
}
if (gz->type->draw_select == NULL) {
continue;
}
bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0; bool is_depth = (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_DEPTH_3D) != 0;
if (is_depth == is_depth_prev) { if (is_depth == is_depth_prev) {
@@ -490,9 +498,6 @@ static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmo
/* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */ /* 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); gz->type->draw_select(C, gz, select_id << 8);
select_id++;
} }
if (is_depth_prev) { if (is_depth_prev) {
@@ -505,7 +510,7 @@ static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmo
static int gizmo_find_intersected_3d_intern( static int gizmo_find_intersected_3d_intern(
ListBase *visible_gizmos, const bContext *C, const int co[2], ListBase *visible_gizmos, const bContext *C, const int co[2],
const int hotspot) const int hotspot, const wmGizmo *gz_stop)
{ {
ScrArea *sa = CTX_wm_area(C); ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C); ARegion *ar = CTX_wm_region(C);
@@ -525,13 +530,13 @@ static int gizmo_find_intersected_3d_intern(
else else
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_ALL, 0); GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_ALL, 0);
/* do the drawing */ /* do the drawing */
gizmo_draw_select_3D_loop(C, visible_gizmos); gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop);
hits = GPU_select_end(); hits = GPU_select_end();
if (do_passes && (hits > 0)) { if (do_passes && (hits > 0)) {
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
gizmo_draw_select_3D_loop(C, visible_gizmos); gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop);
GPU_select_end(); GPU_select_end();
} }
@@ -552,36 +557,56 @@ static wmGizmo *gizmo_find_intersected_3d(
wmGizmo *result = NULL; wmGizmo *result = NULL;
int hit = -1; int hit = -1;
int hotspot_radii[] = {
3 * U.pixelsize,
/* This runs on mouse move, careful doing too many tests! */
10 * U.pixelsize,
};
*r_part = 0; *r_part = 0;
/* set up view matrices */ /* set up view matrices */
view3d_operator_needs_opengl(C); view3d_operator_needs_opengl(C);
hit = -1; /* Search for 3D gizmo's that use the 2D callback for checking intersections. */
bool has_3d = false;
for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) { {
hit = gizmo_find_intersected_3d_intern(visible_gizmos, C, co, hotspot_radii[i]); int select_id = 0;
if (hit != -1) { for (LinkData *link = visible_gizmos->first; link; link = link->next, select_id++) {
break; wmGizmo *gz = link->data;
if (gz->type->test_select) {
if ((*r_part = gz->type->test_select(C, gz, co)) != -1) {
hit = select_id;
result = gz;
break;
}
}
else {
has_3d = true;
}
} }
} }
if (hit != -1) { /* Search for 3D intersections if they're before 2D that have been found (if any).
LinkData *link = BLI_findlink(visible_gizmos, hit >> 8); * This way we always use the first hit. */
if (link != NULL) { if (has_3d) {
*r_part = hit & 255; const int hotspot_radii[] = {
result = link->data; 3 * U.pixelsize,
/* This runs on mouse move, careful doing too many tests! */
10 * U.pixelsize,
};
for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
hit = gizmo_find_intersected_3d_intern(visible_gizmos, C, co, hotspot_radii[i], result);
if (hit != -1) {
break;
}
} }
else {
/* All gizmos should use selection ID they're given as part of the callback, if (hit != -1) {
* if they don't it will attempt tp lookup non-existing index. */ LinkData *link = BLI_findlink(visible_gizmos, hit >> 8);
BLI_assert(0); if (link != NULL) {
*r_part = hit & 255;
result = link->data;
}
else {
/* All gizmos should use selection ID they're given as part of the callback,
* if they don't it will attempt tp lookup non-existing index. */
BLI_assert(0);
}
} }
} }