From c84275d6fa0e160af8c3fe1ced3d1c99c963f31e Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sun, 8 Jan 2012 01:35:11 +0000 Subject: [PATCH] Snap to markers in the audio display on click in addition to on drag Originally committed to SVN as r6237. --- aegisub/src/audio_display.cpp | 8 +-- aegisub/src/audio_timing.h | 9 ++-- aegisub/src/audio_timing_dialogue.cpp | 72 +++++++++++++++------------ aegisub/src/audio_timing_karaoke.cpp | 10 ++-- 4 files changed, 55 insertions(+), 44 deletions(-) diff --git a/aegisub/src/audio_display.cpp b/aegisub/src/audio_display.cpp index 4c7e5fb26..649b63cbc 100644 --- a/aegisub/src/audio_display.cpp +++ b/aegisub/src/audio_display.cpp @@ -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) { diff --git a/aegisub/src/audio_timing.h b/aegisub/src/audio_timing.h index 094262171..3a1967ce4 100644 --- a/aegisub/src/audio_timing.h +++ b/aegisub/src/audio_timing.h @@ -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() { } diff --git a/aegisub/src/audio_timing_dialogue.cpp b/aegisub/src/audio_timing_dialogue.cpp index 410093644..58e4b3717 100644 --- a/aegisub/src/audio_timing_dialogue.cpp +++ b/aegisub/src/audio_timing_dialogue.cpp @@ -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(marker), new_position); + SetMarker(static_cast(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; +} diff --git a/aegisub/src/audio_timing_karaoke.cpp b/aegisub/src/audio_timing_karaoke.cpp index 42d507136..214886c72 100644 --- a/aegisub/src/audio_timing_karaoke.cpp +++ b/aegisub/src/audio_timing_karaoke.cpp @@ -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(m); // No rearranging of syllables allowed new_position = mid(