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(
|
timing_controller->OnMarkerDrag(
|
||||||
marker,
|
marker,
|
||||||
display->SamplesFromRelativeX(event.GetPosition().x),
|
display->SamplesFromRelativeX(event.GetPosition().x),
|
||||||
default_snap != event.ShiftDown(),
|
default_snap != event.ShiftDown() ? display->SamplesFromAbsoluteX(snap_range) : 0);
|
||||||
display->SamplesFromAbsoluteX(snap_range));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We lose the marker drag if the button used to initiate it goes up
|
// 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();
|
AudioTimingController *timing = controller->GetTimingController();
|
||||||
if (!timing) return;
|
if (!timing) return;
|
||||||
int drag_sensitivity = pixel_samples * OPT_GET("Audio/Start Drag Sensitivity")->GetInt();
|
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
|
// Not scrollbar, not timeline, no button action
|
||||||
if (event.Moving())
|
if (event.Moving())
|
||||||
|
@ -1144,8 +1144,8 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
int64_t samplepos = SamplesFromRelativeX(mousepos.x);
|
int64_t samplepos = SamplesFromRelativeX(mousepos.x);
|
||||||
AudioMarker *marker = event.LeftDown() ?
|
AudioMarker *marker = event.LeftDown() ?
|
||||||
timing->OnLeftClick(samplepos, drag_sensitivity) :
|
timing->OnLeftClick(samplepos, drag_sensitivity, snap_sensitivity) :
|
||||||
timing->OnRightClick(samplepos, drag_sensitivity);
|
timing->OnRightClick(samplepos, drag_sensitivity, snap_sensitivity);
|
||||||
|
|
||||||
if (marker)
|
if (marker)
|
||||||
{
|
{
|
||||||
|
|
|
@ -125,25 +125,26 @@ public:
|
||||||
/// @brief The user pressed the left button down at an empty place in the audio
|
/// @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 sample The audio sample index the user clicked
|
||||||
/// @param sensitivity Distance in samples to consider existing markers
|
/// @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
|
/// @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
|
/// starts dragging the mouse after pressing down the button, the returned
|
||||||
/// marker is being dragged.
|
/// 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
|
/// @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 sample The audio sample index the user clicked
|
||||||
/// @param sensitivity Distance in samples to consider existing markers
|
/// @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
|
/// @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
|
/// starts dragging the mouse after pressing down the button, the returned
|
||||||
/// marker is being dragged.
|
/// 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
|
/// @brief The user dragged a timing marker
|
||||||
/// @param marker The marker being dragged
|
/// @param marker The marker being dragged
|
||||||
/// @param new_position Sample position the marker was dragged to
|
/// @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
|
/// @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
|
/// @brief Destructor
|
||||||
virtual ~AudioTimingController() { }
|
virtual ~AudioTimingController() { }
|
||||||
|
|
|
@ -80,7 +80,7 @@ public:
|
||||||
int64_t GetPosition() const { return position; }
|
int64_t GetPosition() const { return position; }
|
||||||
wxPen GetStyle() const { return style; }
|
wxPen GetStyle() const { return style; }
|
||||||
FeetStyle GetFeet() const { return feet; }
|
FeetStyle GetFeet() const { return feet; }
|
||||||
bool CanSnap() const { return true; }
|
bool CanSnap() const { return false; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Specific interface
|
// Specific interface
|
||||||
|
@ -197,6 +197,11 @@ class AudioTimingControllerDialogue : public AudioTimingController, private Sele
|
||||||
/// @param sample New position of the marker
|
/// @param sample New position of the marker
|
||||||
void SetMarker(AudioMarkerDialogueTiming *marker, int64_t sample);
|
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
|
// SubtitleSelectionListener interface
|
||||||
void OnActiveLineChanged(AssDialogue *new_line);
|
void OnActiveLineChanged(AssDialogue *new_line);
|
||||||
void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed);
|
void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed);
|
||||||
|
@ -220,9 +225,9 @@ public:
|
||||||
void Commit();
|
void Commit();
|
||||||
void Revert();
|
void Revert();
|
||||||
bool IsNearbyMarker(int64_t sample, int sensitivity) const;
|
bool IsNearbyMarker(int64_t sample, int sensitivity) const;
|
||||||
AudioMarker * OnLeftClick(int64_t sample, int sensitivity);
|
AudioMarker * OnLeftClick(int64_t sample, int sensitivity, int64_t snap_range);
|
||||||
AudioMarker * OnRightClick(int64_t sample, int sensitivity);
|
AudioMarker * OnRightClick(int64_t sample, int sensitivity, int64_t snap_range);
|
||||||
void OnMarkerDrag(AudioMarker *marker, int64_t new_position, bool snap, int64_t snap_range);
|
void OnMarkerDrag(AudioMarker *marker, int64_t new_position, int64_t snap_range);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Specific interface
|
// 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]);
|
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);
|
assert(sensitivity >= 0);
|
||||||
|
|
||||||
|
@ -497,7 +502,7 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
|
||||||
{
|
{
|
||||||
// Clicked near the left marker:
|
// Clicked near the left marker:
|
||||||
// Insta-move it and start dragging it
|
// Insta-move it and start dragging it
|
||||||
SetMarker(left, sample);
|
SetMarker(left, SnapPosition(sample, snap_range));
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,42 +516,22 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
|
||||||
// Clicked far from either marker:
|
// Clicked far from either marker:
|
||||||
// Insta-set the left marker to the clicked position and return the right as the dragged one,
|
// 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
|
// 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;
|
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();
|
AudioMarkerDialogueTiming *right = GetRightMarker();
|
||||||
SetMarker(right, sample);
|
SetMarker(right, SnapPosition(sample, snap_range));
|
||||||
return right;
|
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]);
|
assert(marker == &active_markers[0] || marker == &active_markers[1]);
|
||||||
|
|
||||||
if (snap)
|
SetMarker(static_cast<AudioMarkerDialogueTiming*>(marker), SnapPosition(new_position, snap_range));
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioTimingControllerDialogue::UpdateSelection()
|
void AudioTimingControllerDialogue::UpdateSelection()
|
||||||
|
@ -606,3 +591,28 @@ void AudioTimingControllerDialogue::RegenerateInactiveLines()
|
||||||
}
|
}
|
||||||
AnnounceUpdatedStyleRanges();
|
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 Commit();
|
||||||
void Revert();
|
void Revert();
|
||||||
bool IsNearbyMarker(int64_t sample, int sensitivity) const;
|
bool IsNearbyMarker(int64_t sample, int sensitivity) const;
|
||||||
AudioMarker * OnLeftClick(int64_t sample, int sensitivity);
|
AudioMarker * OnLeftClick(int64_t sample, int sensitivity, int64_t);
|
||||||
AudioMarker * OnRightClick(int64_t sample, int sensitivity) { return 0; }
|
AudioMarker * OnRightClick(int64_t, int, int64_t) { return 0; }
|
||||||
void OnMarkerDrag(AudioMarker *marker, int64_t new_position, bool, int64_t);
|
void OnMarkerDrag(AudioMarker *marker, int64_t new_position, int64_t);
|
||||||
|
|
||||||
AudioTimingControllerKaraoke(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed);
|
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;
|
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);
|
SampleRange range(sample - sensitivity, sample + sensitivity);
|
||||||
|
|
||||||
size_t syl = distance(markers.begin(), lower_bound(markers.begin(), markers.end(), sample));
|
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;
|
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);
|
KaraokeMarker *marker = static_cast<KaraokeMarker*>(m);
|
||||||
// No rearranging of syllables allowed
|
// No rearranging of syllables allowed
|
||||||
new_position = mid(
|
new_position = mid(
|
||||||
|
|
Loading…
Reference in a new issue