Snap to markers in the audio display on click in addition to on drag
Originally committed to SVN as r6237.
This commit is contained in:
parent
4dcb6240d4
commit
c84275d6fa
4 changed files with 55 additions and 44 deletions
|
@ -511,8 +511,7 @@ public:
|
|||
timing_controller->OnMarkerDrag(
|
||||
marker,
|
||||
display->SamplesFromRelativeX(event.GetPosition().x),
|
||||
default_snap != event.ShiftDown(),
|
||||
display->SamplesFromAbsoluteX(snap_range));
|
||||
default_snap != event.ShiftDown() ? display->SamplesFromAbsoluteX(snap_range) : 0);
|
||||
}
|
||||
|
||||
// We lose the marker drag if the button used to initiate it goes up
|
||||
|
@ -1128,6 +1127,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event)
|
|||
AudioTimingController *timing = controller->GetTimingController();
|
||||
if (!timing) return;
|
||||
int drag_sensitivity = pixel_samples * OPT_GET("Audio/Start Drag Sensitivity")->GetInt();
|
||||
int snap_sensitivity = OPT_GET("Audio/Snap/Enable")->GetBool() != event.ShiftDown() ? pixel_samples * OPT_GET("Audio/Snap/Distance")->GetInt() : 0;
|
||||
|
||||
// Not scrollbar, not timeline, no button action
|
||||
if (event.Moving())
|
||||
|
@ -1144,8 +1144,8 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event)
|
|||
{
|
||||
int64_t samplepos = SamplesFromRelativeX(mousepos.x);
|
||||
AudioMarker *marker = event.LeftDown() ?
|
||||
timing->OnLeftClick(samplepos, drag_sensitivity) :
|
||||
timing->OnRightClick(samplepos, drag_sensitivity);
|
||||
timing->OnLeftClick(samplepos, drag_sensitivity, snap_sensitivity) :
|
||||
timing->OnRightClick(samplepos, drag_sensitivity, snap_sensitivity);
|
||||
|
||||
if (marker)
|
||||
{
|
||||
|
|
|
@ -125,25 +125,26 @@ public:
|
|||
/// @brief The user pressed the left button down at an empty place in the audio
|
||||
/// @param sample The audio sample index the user clicked
|
||||
/// @param sensitivity Distance in samples to consider existing markers
|
||||
/// @param snap_range Maximum snapping range in samples
|
||||
/// @return An audio marker or 0. If a marker is returned and the user
|
||||
/// starts dragging the mouse after pressing down the button, the returned
|
||||
/// marker is being dragged.
|
||||
virtual AudioMarker * OnLeftClick(int64_t sample, int sensitivity) = 0;
|
||||
virtual AudioMarker * OnLeftClick(int64_t sample, int sensitivity, int64_t snap_range) = 0;
|
||||
|
||||
/// @brief The user pressed the right button down at an empty place in the audio
|
||||
/// @param sample The audio sample index the user clicked
|
||||
/// @param sensitivity Distance in samples to consider existing markers
|
||||
/// @param snap_range Maximum snapping range in samples
|
||||
/// @return An audio marker or 0. If a marker is returned and the user
|
||||
/// starts dragging the mouse after pressing down the button, the returned
|
||||
/// marker is being dragged.
|
||||
virtual AudioMarker * OnRightClick(int64_t sample, int sensitivity) = 0;
|
||||
virtual AudioMarker * OnRightClick(int64_t sample, int sensitivity, int64_t snap_range) = 0;
|
||||
|
||||
/// @brief The user dragged a timing marker
|
||||
/// @param marker The marker being dragged
|
||||
/// @param new_position Sample position the marker was dragged to
|
||||
/// @param snap Enable snapping to other markers
|
||||
/// @param snap_range Maximum snapping range in samples
|
||||
virtual void OnMarkerDrag(AudioMarker *marker, int64_t new_position, bool snap, int64_t snap_range) = 0;
|
||||
virtual void OnMarkerDrag(AudioMarker *marker, int64_t new_position, int64_t snap_range) = 0;
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~AudioTimingController() { }
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
int64_t GetPosition() const { return position; }
|
||||
wxPen GetStyle() const { return style; }
|
||||
FeetStyle GetFeet() const { return feet; }
|
||||
bool CanSnap() const { return true; }
|
||||
bool CanSnap() const { return false; }
|
||||
|
||||
public:
|
||||
// Specific interface
|
||||
|
@ -197,6 +197,11 @@ class AudioTimingControllerDialogue : public AudioTimingController, private Sele
|
|||
/// @param sample New position of the marker
|
||||
void SetMarker(AudioMarkerDialogueTiming *marker, int64_t sample);
|
||||
|
||||
/// Snap a position to a nearby marker, if any
|
||||
/// @param position Position to snap
|
||||
/// @param snap_range Maximum distance to snap in samples
|
||||
int64_t SnapPosition(int64_t position, int64_t snap_range) const;
|
||||
|
||||
// SubtitleSelectionListener interface
|
||||
void OnActiveLineChanged(AssDialogue *new_line);
|
||||
void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed);
|
||||
|
@ -220,9 +225,9 @@ public:
|
|||
void Commit();
|
||||
void Revert();
|
||||
bool IsNearbyMarker(int64_t sample, int sensitivity) const;
|
||||
AudioMarker * OnLeftClick(int64_t sample, int sensitivity);
|
||||
AudioMarker * OnRightClick(int64_t sample, int sensitivity);
|
||||
void OnMarkerDrag(AudioMarker *marker, int64_t new_position, bool snap, int64_t snap_range);
|
||||
AudioMarker * OnLeftClick(int64_t sample, int sensitivity, int64_t snap_range);
|
||||
AudioMarker * OnRightClick(int64_t sample, int sensitivity, int64_t snap_range);
|
||||
void OnMarkerDrag(AudioMarker *marker, int64_t new_position, int64_t snap_range);
|
||||
|
||||
public:
|
||||
// Specific interface
|
||||
|
@ -481,7 +486,7 @@ bool AudioTimingControllerDialogue::IsNearbyMarker(int64_t sample, int sensitivi
|
|||
return range.contains(active_markers[0]) || range.contains(active_markers[1]);
|
||||
}
|
||||
|
||||
AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sensitivity)
|
||||
AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sensitivity, int64_t snap_range)
|
||||
{
|
||||
assert(sensitivity >= 0);
|
||||
|
||||
|
@ -497,7 +502,7 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
|
|||
{
|
||||
// Clicked near the left marker:
|
||||
// Insta-move it and start dragging it
|
||||
SetMarker(left, sample);
|
||||
SetMarker(left, SnapPosition(sample, snap_range));
|
||||
return left;
|
||||
}
|
||||
|
||||
|
@ -511,42 +516,22 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
|
|||
// Clicked far from either marker:
|
||||
// Insta-set the left marker to the clicked position and return the right as the dragged one,
|
||||
// such that if the user does start dragging, he will create a new selection from scratch
|
||||
SetMarker(left, sample);
|
||||
SetMarker(left, SnapPosition(sample, snap_range));
|
||||
return right;
|
||||
}
|
||||
|
||||
AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int sensitivity)
|
||||
AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int sensitivity, int64_t snap_range)
|
||||
{
|
||||
AudioMarkerDialogueTiming *right = GetRightMarker();
|
||||
SetMarker(right, sample);
|
||||
SetMarker(right, SnapPosition(sample, snap_range));
|
||||
return right;
|
||||
}
|
||||
|
||||
void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t new_position, bool snap, int64_t snap_range)
|
||||
void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t new_position, int64_t snap_range)
|
||||
{
|
||||
assert(marker == &active_markers[0] || marker == &active_markers[1]);
|
||||
|
||||
if (snap)
|
||||
{
|
||||
SampleRange snap_sample_range(new_position - snap_range, new_position + snap_range);
|
||||
const AudioMarker *snap_marker = 0;
|
||||
AudioMarkerVector potential_snaps;
|
||||
GetMarkers(snap_sample_range, potential_snaps);
|
||||
for (AudioMarkerVector::iterator mi = potential_snaps.begin(); mi != potential_snaps.end(); ++mi)
|
||||
{
|
||||
if (*mi != marker && (*mi)->CanSnap())
|
||||
{
|
||||
if (!snap_marker)
|
||||
snap_marker = *mi;
|
||||
else if (tabs((*mi)->GetPosition() - new_position) < tabs(snap_marker->GetPosition() - new_position))
|
||||
snap_marker = *mi;
|
||||
}
|
||||
}
|
||||
|
||||
if (snap_marker)
|
||||
new_position = snap_marker->GetPosition();
|
||||
}
|
||||
SetMarker(static_cast<AudioMarkerDialogueTiming*>(marker), new_position);
|
||||
SetMarker(static_cast<AudioMarkerDialogueTiming*>(marker), SnapPosition(new_position, snap_range));
|
||||
}
|
||||
|
||||
void AudioTimingControllerDialogue::UpdateSelection()
|
||||
|
@ -606,3 +591,28 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines()
|
|||
}
|
||||
AnnounceUpdatedStyleRanges();
|
||||
}
|
||||
|
||||
int64_t AudioTimingControllerDialogue::SnapPosition(int64_t position, int64_t snap_range) const
|
||||
{
|
||||
if (snap_range <= 0)
|
||||
return position;
|
||||
|
||||
SampleRange snap_sample_range(position - snap_range, position + snap_range);
|
||||
const AudioMarker *snap_marker = 0;
|
||||
AudioMarkerVector potential_snaps;
|
||||
GetMarkers(snap_sample_range, potential_snaps);
|
||||
for (AudioMarkerVector::iterator mi = potential_snaps.begin(); mi != potential_snaps.end(); ++mi)
|
||||
{
|
||||
if ((*mi)->CanSnap())
|
||||
{
|
||||
if (!snap_marker)
|
||||
snap_marker = *mi;
|
||||
else if (tabs((*mi)->GetPosition() - position) < tabs(snap_marker->GetPosition() - position))
|
||||
snap_marker = *mi;
|
||||
}
|
||||
}
|
||||
|
||||
if (snap_marker)
|
||||
return snap_marker->GetPosition();
|
||||
return position;
|
||||
}
|
||||
|
|
|
@ -130,9 +130,9 @@ public:
|
|||
void Commit();
|
||||
void Revert();
|
||||
bool IsNearbyMarker(int64_t sample, int sensitivity) const;
|
||||
AudioMarker * OnLeftClick(int64_t sample, int sensitivity);
|
||||
AudioMarker * OnRightClick(int64_t sample, int sensitivity) { return 0; }
|
||||
void OnMarkerDrag(AudioMarker *marker, int64_t new_position, bool, int64_t);
|
||||
AudioMarker * OnLeftClick(int64_t sample, int sensitivity, int64_t);
|
||||
AudioMarker * OnRightClick(int64_t, int, int64_t) { return 0; }
|
||||
void OnMarkerDrag(AudioMarker *marker, int64_t new_position, int64_t);
|
||||
|
||||
AudioTimingControllerKaraoke(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed);
|
||||
};
|
||||
|
@ -284,7 +284,7 @@ bool AudioTimingControllerKaraoke::IsNearbyMarker(int64_t sample, int sensitivit
|
|||
return false;
|
||||
}
|
||||
|
||||
AudioMarker *AudioTimingControllerKaraoke::OnLeftClick(int64_t sample, int sensitivity) {
|
||||
AudioMarker *AudioTimingControllerKaraoke::OnLeftClick(int64_t sample, int sensitivity, int64_t) {
|
||||
SampleRange range(sample - sensitivity, sample + sensitivity);
|
||||
|
||||
size_t syl = distance(markers.begin(), lower_bound(markers.begin(), markers.end(), sample));
|
||||
|
@ -301,7 +301,7 @@ AudioMarker *AudioTimingControllerKaraoke::OnLeftClick(int64_t sample, int sensi
|
|||
return 0;
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::OnMarkerDrag(AudioMarker *m, int64_t new_position, bool, int64_t) {
|
||||
void AudioTimingControllerKaraoke::OnMarkerDrag(AudioMarker *m, int64_t new_position, int64_t) {
|
||||
KaraokeMarker *marker = static_cast<KaraokeMarker*>(m);
|
||||
// No rearranging of syllables allowed
|
||||
new_position = mid(
|
||||
|
|
Loading…
Reference in a new issue