diff --git a/src/libse/Common/ShotChangeHelper.cs b/src/libse/Common/ShotChangeHelper.cs index f4042b77c..48c196c54 100644 --- a/src/libse/Common/ShotChangeHelper.cs +++ b/src/libse/Common/ShotChangeHelper.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using Nikse.SubtitleEdit.Core.Forms; +using Nikse.SubtitleEdit.Core.SubtitleFormats; namespace Nikse.SubtitleEdit.Core.Common { @@ -99,5 +101,40 @@ namespace Nikse.SubtitleEdit.Core.Common { return GetNextShotChangeInMs(shotChanges, currentTime) - TimeCodesBeautifierUtils.GetOutCuesGapMs(); } + + public static double? GetClosestShotChangeInMs(List shotChanges, TimeCode currentTime) + { + try + { + return shotChanges.Aggregate((x, y) => Math.Abs(x - currentTime.TotalSeconds) < Math.Abs(y - currentTime.TotalSeconds) ? x : y); + } + catch (InvalidOperationException) + { + return null; + } + } + + public static bool IsCueOnShotChange(List shotChanges, TimeCode currentTime, bool isInCue) + { + var closestShotChange = GetClosestShotChangeInMs(shotChanges, currentTime); + if (closestShotChange != null) + { + var currentFrame = SubtitleFormat.MillisecondsToFrames(currentTime.TotalSeconds * 1000); + var closestShotChangeFrame = SubtitleFormat.MillisecondsToFrames(closestShotChange.Value * 1000); + + if (isInCue) + { + return currentFrame >= closestShotChangeFrame && currentFrame <= closestShotChangeFrame + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap; + } + else + { + return currentFrame <= closestShotChangeFrame && currentFrame >= closestShotChangeFrame - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap; + } + } + else + { + return false; + } + } } } \ No newline at end of file diff --git a/src/libse/Forms/TimeCodesBeautifier.cs b/src/libse/Forms/TimeCodesBeautifier.cs index c6338e192..fab0ef951 100644 --- a/src/libse/Forms/TimeCodesBeautifier.cs +++ b/src/libse/Forms/TimeCodesBeautifier.cs @@ -487,26 +487,6 @@ namespace Nikse.SubtitleEdit.Core.Forms return true; } - private bool IsCueOnShotChange(int cueFrame, bool isInCue) - { - var closestShotChangeFrame = GetClosestShotChangeFrame(cueFrame); - if (closestShotChangeFrame != null) - { - if (isInCue) - { - return cueFrame >= closestShotChangeFrame.Value && cueFrame <= closestShotChangeFrame.Value + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap; - } - else - { - return cueFrame <= closestShotChangeFrame.Value && cueFrame >= closestShotChangeFrame.Value - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap; - } - } - else - { - return false; - } - } - private int? GetFixedChainableSubtitlesLeftOutCueFrameGeneral(int leftOutCueFrame, int rightInCueFrame, Paragraph leftParagraph = null, Paragraph rightParagraph = null) { // Check if zones are being used @@ -852,6 +832,26 @@ namespace Nikse.SubtitleEdit.Core.Forms } } + private bool IsCueOnShotChange(int cueFrame, bool isInCue) + { + var closestShotChangeFrame = GetClosestShotChangeFrame(cueFrame); + if (closestShotChangeFrame != null) + { + if (isInCue) + { + return cueFrame >= closestShotChangeFrame.Value && cueFrame <= closestShotChangeFrame.Value + Configuration.Settings.BeautifyTimeCodes.Profile.InCuesGap; + } + else + { + return cueFrame <= closestShotChangeFrame.Value && cueFrame >= closestShotChangeFrame.Value - Configuration.Settings.BeautifyTimeCodes.Profile.OutCuesGap; + } + } + else + { + return false; + } + } + // Delegates diff --git a/src/ui/Forms/Main.cs b/src/ui/Forms/Main.cs index 88638fd2c..b09a86f78 100644 --- a/src/ui/Forms/Main.cs +++ b/src/ui/Forms/Main.cs @@ -18369,6 +18369,32 @@ namespace Nikse.SubtitleEdit.Forms private void ExtendSelectedLinesToNextLine(bool minusChainingGap = false) { + double GetNextStartTimeMinusChainingGap(Paragraph next) + { + if (ShotChangeHelper.IsCueOnShotChange(audioVisualizer.ShotChanges, next.StartTime, true)) + { + if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotUseZones) + { + return next.StartTime.TotalMilliseconds - SubtitleFormat.FramesToMilliseconds(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotLeftGreenZone); + } + else + { + return next.StartTime.TotalMilliseconds - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingInCueOnShotMaxGap; + } + } + else + { + if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones) + { + return next.StartTime.TotalMilliseconds - SubtitleFormat.FramesToMilliseconds(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone); + } + else + { + return next.StartTime.TotalMilliseconds - Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap; + } + } + } + var historyAdded = false; foreach (ListViewItem selectedItem in SubtitleListview1.SelectedItems) { @@ -18385,12 +18411,17 @@ namespace Nikse.SubtitleEdit.Forms if (minusChainingGap) { - // TODO chaining gap + p.EndTime.TotalMilliseconds = GetNextStartTimeMinusChainingGap(next); } else { p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - MinGapBetweenLines; } + + if (p.Duration.TotalMilliseconds < 0) + { + p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds; + } } if (IsOriginalEditable) @@ -18409,12 +18440,17 @@ namespace Nikse.SubtitleEdit.Forms if (minusChainingGap) { - // TODO chaining gap + original.EndTime.TotalMilliseconds = GetNextStartTimeMinusChainingGap(originalNext); } else { original.EndTime.TotalMilliseconds = originalNext.StartTime.TotalMilliseconds - MinGapBetweenLines; } + + if (original.Duration.TotalMilliseconds < 0) + { + original.EndTime.TotalMilliseconds = original.StartTime.TotalMilliseconds; + } } } } @@ -18425,6 +18461,32 @@ namespace Nikse.SubtitleEdit.Forms private void ExtendSelectedLinesToPreviousLine(bool minusChainingGap = false) { + double GetPreviousEndTimePlusChainingGap(Paragraph previous) + { + if (ShotChangeHelper.IsCueOnShotChange(audioVisualizer.ShotChanges, previous.EndTime, false)) + { + if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotUseZones) + { + return previous.EndTime.TotalMilliseconds + SubtitleFormat.FramesToMilliseconds(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotRightGreenZone); + } + else + { + return previous.EndTime.TotalMilliseconds + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingOutCueOnShotMaxGap; + } + } + else + { + if (Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralUseZones) + { + return previous.EndTime.TotalMilliseconds + SubtitleFormat.FramesToMilliseconds(Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralLeftGreenZone); + } + else + { + return previous.EndTime.TotalMilliseconds + Configuration.Settings.BeautifyTimeCodes.Profile.ChainingGeneralMaxGap; + } + } + } + var historyAdded = false; foreach (ListViewItem selectedItem in SubtitleListview1.SelectedItems) { @@ -18449,12 +18511,17 @@ namespace Nikse.SubtitleEdit.Forms if (minusChainingGap) { - // TODO chaining gap + original.StartTime.TotalMilliseconds = GetPreviousEndTimePlusChainingGap(originalPrevious); } else { original.StartTime.TotalMilliseconds = originalPrevious.EndTime.TotalMilliseconds + MinGapBetweenLines; } + + if (original.Duration.TotalMilliseconds < 0) + { + original.StartTime.TotalMilliseconds = original.EndTime.TotalMilliseconds; + } } } } @@ -18467,12 +18534,17 @@ namespace Nikse.SubtitleEdit.Forms if (minusChainingGap) { - // TODO chaining gap + p.StartTime.TotalMilliseconds = GetPreviousEndTimePlusChainingGap(previous); } else { p.StartTime.TotalMilliseconds = previous.EndTime.TotalMilliseconds + MinGapBetweenLines; } + + if (p.Duration.TotalMilliseconds < 0) + { + p.StartTime.TotalMilliseconds = p.EndTime.TotalMilliseconds; + } } RefreshSelectedParagraphs();