Fix T100491: Mouse selection is inaccurate in NLA Editor

Selection range is +/-7 pixels to actual clicked position, but strip selection
was biased towards rightmost strip.

To make selection more intuitive, select closest strip to clicked position, and
stop iterating when strip intersects clicked pixel.

Reviewed By: sybren

Differential Revision: https://developer.blender.org/D15728
This commit is contained in:
Richard Antalik 2022-11-14 19:57:42 +01:00
parent edae67c036
commit 970be7e65a
Notes: blender-bot 2023-04-04 07:45:26 +02:00
Referenced by issue #100491, Mouse selection is inaccurate in NLA Editor
3 changed files with 34 additions and 2 deletions

View File

@ -279,6 +279,11 @@ void BKE_nlastrip_set_active(struct AnimData *adt, struct NlaStrip *strip);
* Does the given NLA-strip fall within the given bounds (times)?.
*/
bool BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
/**
* Return the distance from the given frame to the NLA strip, measured in frames.
* If the given frame intersects the NLA strip, the distance is zero.
*/
float BKE_nlastrip_distance_to_frame(const struct NlaStrip *strip, float timeline_frame);
/**
* Recalculate the start and end frames for the current strip, after changing
* the extents of the action or the mapping (repeats or scale factor) info.

View File

@ -1360,6 +1360,17 @@ bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max)
return true;
}
float BKE_nlastrip_distance_to_frame(const NlaStrip *strip, const float timeline_frame)
{
if (timeline_frame < strip->start) {
return strip->start - timeline_frame;
}
if (strip->end < timeline_frame) {
return timeline_frame - strip->end;
}
return 0.0f;
}
/* Ensure that strip doesn't overlap those around it after resizing
* by offsetting those which follow. */
static void nlastrip_fix_resize_overlaps(NlaStrip *strip)

View File

@ -14,6 +14,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_math_base.h"
#include "BKE_context.h"
#include "BKE_nla.h"
@ -286,20 +287,35 @@ static void nlaedit_strip_at_region_position(
/* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
* (that is the size of keyframe icons, so user should be expecting similar tolerances)
*/
float xmin = UI_view2d_region_to_view_x(v2d, region_x - 7);
float xmax = UI_view2d_region_to_view_x(v2d, region_x + 7);
const float mouse_x = UI_view2d_region_to_view_x(v2d, region_x);
const float xmin = UI_view2d_region_to_view_x(v2d, region_x - 7);
const float xmax = UI_view2d_region_to_view_x(v2d, region_x + 7);
bAnimListElem *ale = BLI_findlink(&anim_data, channel_index);
if (ale != NULL) {
if (ale->type == ANIMTYPE_NLATRACK) {
NlaTrack *nlt = (NlaTrack *)ale->data;
float best_distance = MAXFRAMEF;
LISTBASE_FOREACH (NlaStrip *, strip, &nlt->strips) {
if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) {
const float distance = BKE_nlastrip_distance_to_frame(strip, mouse_x);
/* Skip if strip is further away from mouse cursor than any previous strip. */
if (distance > best_distance) {
continue;
}
*r_ale = ale;
*r_strip = strip;
best_distance = distance;
BLI_remlink(&anim_data, ale);
/* Mouse cursor was directly on strip, no need to check other strips. */
if (distance == 0.0f) {
break;
}
}
}
}