forked from mia/Aegisub
Fix snapping audio markers to markers from other selected lines
This commit is contained in:
parent
e593843da7
commit
6f36c75cfd
1 changed files with 66 additions and 21 deletions
|
@ -223,9 +223,11 @@ public:
|
||||||
|
|
||||||
/// Get the leftmost of the markers
|
/// Get the leftmost of the markers
|
||||||
DialogueTimingMarker *GetLeftMarker() { return left_marker; }
|
DialogueTimingMarker *GetLeftMarker() { return left_marker; }
|
||||||
|
const DialogueTimingMarker *GetLeftMarker() const { return left_marker; }
|
||||||
|
|
||||||
/// Get the rightmost of the markers
|
/// Get the rightmost of the markers
|
||||||
DialogueTimingMarker *GetRightMarker() { return right_marker; }
|
DialogueTimingMarker *GetRightMarker() { return right_marker; }
|
||||||
|
const DialogueTimingMarker *GetRightMarker() const { return right_marker; }
|
||||||
|
|
||||||
/// Does this line have a marker in the given range?
|
/// Does this line have a marker in the given range?
|
||||||
bool ContainsMarker(TimeRange const& range) const
|
bool ContainsMarker(TimeRange const& range) const
|
||||||
|
@ -861,41 +863,84 @@ std::vector<AudioMarker*> AudioTimingControllerDialogue::GetRightMarkers()
|
||||||
|
|
||||||
int AudioTimingControllerDialogue::SnapMarkers(int snap_range, std::vector<AudioMarker*> const& active) const
|
int AudioTimingControllerDialogue::SnapMarkers(int snap_range, std::vector<AudioMarker*> const& active) const
|
||||||
{
|
{
|
||||||
if (snap_range <= 0) return 0;
|
if (snap_range <= 0 || active.empty()) return 0;
|
||||||
|
|
||||||
|
auto marker_range = [&] {
|
||||||
|
int front = active.front()->GetPosition();
|
||||||
|
int min = front;
|
||||||
|
int max = front;
|
||||||
|
for (auto m : active)
|
||||||
|
{
|
||||||
|
auto pos = m->GetPosition();
|
||||||
|
if (pos < min) min = pos;
|
||||||
|
if (pos > max) max = pos;
|
||||||
|
}
|
||||||
|
return TimeRange{min - snap_range, max + snap_range};
|
||||||
|
}();
|
||||||
|
|
||||||
|
std::vector<int> inactive_markers;
|
||||||
|
inactive_markers.reserve(inactive_lines.size() * 2 + selected_lines.size() * 2 + 2 - active.size());
|
||||||
|
|
||||||
|
auto add_inactive = [&](const DialogueTimingMarker *m, bool check)
|
||||||
|
{
|
||||||
|
if (!marker_range.contains(*m)) return;
|
||||||
|
if (!inactive_markers.empty() && inactive_markers.back() == *m) return;
|
||||||
|
if (check && boost::find(active, m) != end(active)) return;
|
||||||
|
inactive_markers.push_back(*m);
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<const DialogueTimingMarker *> inactive_markers;
|
|
||||||
inactive_markers.reserve(inactive_lines.size() * 2);
|
|
||||||
for (auto const& line : inactive_lines)
|
for (auto const& line : inactive_lines)
|
||||||
line.GetMarkers(&inactive_markers);
|
{
|
||||||
|
add_inactive(line.GetLeftMarker(), false);
|
||||||
|
add_inactive(line.GetRightMarker(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active.size() != selected_lines.size() * 2 + 2)
|
||||||
|
{
|
||||||
|
for (auto const& line : selected_lines)
|
||||||
|
{
|
||||||
|
add_inactive(line.GetLeftMarker(), true);
|
||||||
|
add_inactive(line.GetRightMarker(), true);
|
||||||
|
}
|
||||||
|
add_inactive(active_line.GetLeftMarker(), true);
|
||||||
|
add_inactive(active_line.GetRightMarker(), true);
|
||||||
|
}
|
||||||
|
|
||||||
AudioMarkerVector potential_snaps;
|
|
||||||
int snap_distance = 0;
|
int snap_distance = 0;
|
||||||
bool has_snapped = false;
|
bool has_snapped = false;
|
||||||
|
auto check = [&](int marker, int pos)
|
||||||
|
{
|
||||||
|
auto dist = marker - pos;
|
||||||
|
if (!has_snapped)
|
||||||
|
snap_distance = dist;
|
||||||
|
else if (tabs(dist) < tabs(snap_distance))
|
||||||
|
snap_distance = dist;
|
||||||
|
has_snapped = true;
|
||||||
|
};
|
||||||
|
|
||||||
int prev = -1;
|
int prev = -1;
|
||||||
|
AudioMarkerVector snap_markers;
|
||||||
for (const auto active_marker : active)
|
for (const auto active_marker : active)
|
||||||
{
|
{
|
||||||
auto pos = active_marker->GetPosition();
|
auto pos = active_marker->GetPosition();
|
||||||
if (pos == prev) continue;
|
if (pos == prev) continue;
|
||||||
|
|
||||||
potential_snaps.clear();
|
snap_markers.clear();
|
||||||
TimeRange range(pos - snap_range, pos + snap_range);
|
TimeRange range(pos - snap_range, pos + snap_range);
|
||||||
keyframes_provider.GetMarkers(range, potential_snaps);
|
keyframes_provider.GetMarkers(range, snap_markers);
|
||||||
video_position_provider.GetMarkers(range, potential_snaps);
|
video_position_provider.GetMarkers(range, snap_markers);
|
||||||
copy(
|
|
||||||
boost::lower_bound(inactive_markers, range.begin(), marker_ptr_cmp()),
|
|
||||||
boost::upper_bound(inactive_markers, range.end(), marker_ptr_cmp()),
|
|
||||||
back_inserter(potential_snaps));
|
|
||||||
|
|
||||||
for (auto marker : potential_snaps)
|
for (const auto marker : snap_markers)
|
||||||
{
|
{
|
||||||
auto dist = marker->GetPosition() - pos;
|
check(marker->GetPosition(), pos);
|
||||||
if (!has_snapped)
|
if (snap_distance == 0) return 0;
|
||||||
snap_distance = dist;
|
}
|
||||||
else if (tabs(dist) < tabs(snap_distance))
|
|
||||||
snap_distance = dist;
|
for (auto it = boost::lower_bound(inactive_markers, range.begin()); it != end(inactive_markers); ++it)
|
||||||
if (snap_distance == 0)
|
{
|
||||||
return 0;
|
check(*it, pos);
|
||||||
has_snapped = true;
|
if (snap_distance == 0) return 0;
|
||||||
|
if (*it > pos) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue