Fix snapping audio markers to markers from other selected lines

This commit is contained in:
Thomas Goyne 2014-05-15 07:13:09 -07:00
parent e593843da7
commit 6f36c75cfd

View file

@ -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;
} }
} }