private string Complete_Sliders(SliderCompletionatorVm arg, BackgroundWorker worker, DoWorkEventArgs _) { int slidersCompleted = 0; var reader = EditorReaderStuff.GetFullEditorReaderOrNot(out var editorReaderException1); if (arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Selected && editorReaderException1 != null) { throw new Exception("Could not fetch selected hit objects.", editorReaderException1); } foreach (string path in arg.Paths) { var editor = EditorReaderStuff.GetNewestVersionOrNot(path, reader, out var selected, out var editorReaderException2); if (arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Selected && editorReaderException2 != null) { throw new Exception("Could not fetch selected hit objects.", editorReaderException2); } Beatmap beatmap = editor.Beatmap; Timing timing = beatmap.BeatmapTiming; List <HitObject> markedObjects = arg.ImportModeSetting switch { SliderCompletionatorVm.ImportMode.Selected => selected, SliderCompletionatorVm.ImportMode.Bookmarked => beatmap.GetBookmarkedObjects(), SliderCompletionatorVm.ImportMode.Time => beatmap.QueryTimeCode(arg.TimeCode).ToList(), SliderCompletionatorVm.ImportMode.Everything => beatmap.HitObjects, _ => throw new ArgumentException("Unexpected import mode.") }; for (int i = 0; i < markedObjects.Count; i++) { HitObject ho = markedObjects[i]; if (ho.IsSlider) { double mpb = timing.GetMpBAtTime(ho.Time); double oldDuration = timing.CalculateSliderTemporalLength(ho.Time, ho.PixelLength); double oldLength = ho.PixelLength; double oldSv = timing.GetSvAtTime(ho.Time); double newDuration = arg.UseEndTime ? arg.EndTime == -1 ? oldDuration : arg.EndTime - ho.Time : arg.Duration == -1 ? oldDuration : timing.WalkBeatsInMillisecondTime(arg.Duration, ho.Time) - ho.Time; double newLength = arg.Length == -1 ? oldLength : ho.GetSliderPath(fullLength: true).Distance *arg.Length; double newSv = arg.SliderVelocity == -1 ? oldSv : -100 / arg.SliderVelocity; switch (arg.FreeVariableSetting) { case SliderCompletionatorVm.FreeVariable.Velocity: newSv = -10000 * timing.SliderMultiplier * newDuration / (newLength * mpb); break; case SliderCompletionatorVm.FreeVariable.Duration: // This actually doesn't get used anymore because the .osu doesn't store the duration newDuration = newLength * newSv * mpb / (-10000 * timing.SliderMultiplier); break; case SliderCompletionatorVm.FreeVariable.Length: newLength = -10000 * timing.SliderMultiplier * newDuration / (newSv * mpb); break; default: throw new ArgumentException("Unexpected free variable setting."); } if (double.IsNaN(newSv)) { throw new Exception("Encountered NaN slider velocity. Make sure none of the inputs are zero."); } if (newDuration < 0) { throw new Exception("Encountered slider with negative duration. Make sure the end time is greater than the end time of all selected sliders."); } ho.SliderVelocity = newSv; ho.PixelLength = newLength; // Scale anchors to completion if (arg.MoveAnchors) { ho.SetAllCurvePoints(SliderPathUtil.MoveAnchorsToLength( ho.GetAllCurvePoints(), ho.SliderType, ho.PixelLength, out var pathType)); ho.SliderType = pathType; } slidersCompleted++; } if (worker != null && worker.WorkerReportsProgress) { worker.ReportProgress(i / markedObjects.Count); } } // Reconstruct SliderVelocity List <TimingPointsChange> timingPointsChanges = new List <TimingPointsChange>(); // Add Hitobject stuff foreach (HitObject ho in beatmap.HitObjects) { // SliderVelocity changes if (ho.IsSlider) { if (markedObjects.Contains(ho) && arg.DelegateToBpm) { var tpAfter = timing.GetRedlineAtTime(ho.Time).Copy(); var tpOn = tpAfter.Copy(); tpAfter.Offset = ho.Time; tpOn.Offset = ho.Time - 1; // This one will be on the slider tpAfter.OmitFirstBarLine = true; tpOn.OmitFirstBarLine = true; // Express velocity in BPM tpOn.MpB *= ho.SliderVelocity / -100; // NaN SV results in removal of slider ticks ho.SliderVelocity = arg.RemoveSliderTicks ? double.NaN : -100; // Add redlines timingPointsChanges.Add(new TimingPointsChange(tpOn, mpb: true, unInherited: true, omitFirstBarLine: true, fuzzyness: Precision.DOUBLE_EPSILON)); timingPointsChanges.Add(new TimingPointsChange(tpAfter, mpb: true, unInherited: true, omitFirstBarLine: true, fuzzyness: Precision.DOUBLE_EPSILON)); ho.Time -= 1; } TimingPoint tp = ho.TimingPoint.Copy(); tp.Offset = ho.Time; tp.MpB = ho.SliderVelocity; timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true, fuzzyness: Precision.DOUBLE_EPSILON)); } } // Add the new SliderVelocity changes TimingPointsChange.ApplyChanges(timing, timingPointsChanges); // Save the file editor.SaveFile(); } // Complete progressbar if (worker != null && worker.WorkerReportsProgress) { worker.ReportProgress(100); } // Do stuff RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, reader != null, arg.Quick)); // Make an accurate message string message = ""; if (Math.Abs(slidersCompleted) == 1) { message += "Successfully completed " + slidersCompleted + " slider!"; } else { message += "Successfully completed " + slidersCompleted + " sliders!"; } return(arg.Quick ? "" : message); }
private string Complete_Sliders(SliderCompletionatorVm arg, BackgroundWorker worker, DoWorkEventArgs _) { int slidersCompleted = 0; var reader = EditorReaderStuff.GetFullEditorReaderOrNot(out var editorReaderException1); if (arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Selected && editorReaderException1 != null) { throw new Exception("Could not fetch selected hit objects.", editorReaderException1); } foreach (string path in arg.Paths) { var editor = EditorReaderStuff.GetNewestVersionOrNot(path, reader, out var selected, out var editorReaderException2); if (arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Selected && editorReaderException2 != null) { throw new Exception("Could not fetch selected hit objects.", editorReaderException2); } Beatmap beatmap = editor.Beatmap; Timing timing = beatmap.BeatmapTiming; List <HitObject> markedObjects = arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Selected ? selected : arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Bookmarked ? beatmap.GetBookmarkedObjects() : arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Time ? beatmap.QueryTimeCode(arg.TimeCode).ToList() : beatmap.HitObjects; for (int i = 0; i < markedObjects.Count; i++) { HitObject ho = markedObjects[i]; if (ho.IsSlider) { double oldSpatialLength = ho.PixelLength; double newSpatialLength = arg.SpatialLength != -1 ? ho.GetSliderPath(fullLength: true).Distance *arg.SpatialLength : oldSpatialLength; double oldTemporalLength = timing.CalculateSliderTemporalLength(ho.Time, ho.PixelLength); double newTemporalLength = arg.TemporalLength != -1 ? timing.GetMpBAtTime(ho.Time) * arg.TemporalLength : oldTemporalLength; double oldSv = timing.GetSvAtTime(ho.Time); double newSv = oldSv / ((newSpatialLength / oldSpatialLength) / (newTemporalLength / oldTemporalLength)); if (double.IsNaN(newSv)) { throw new Exception("Encountered NaN slider velocity. Make sure none of the inputs are zero."); } ho.SliderVelocity = newSv; ho.PixelLength = newSpatialLength; // Scale anchors to completion if (arg.MoveAnchors) { ho.SetAllCurvePoints(SliderPathUtil.MoveAnchorsToLength( ho.GetAllCurvePoints(), ho.SliderType, ho.PixelLength, out var pathType)); ho.SliderType = pathType; } slidersCompleted++; } if (worker != null && worker.WorkerReportsProgress) { worker.ReportProgress(i / markedObjects.Count); } } // Reconstruct SliderVelocity List <TimingPointsChange> timingPointsChanges = new List <TimingPointsChange>(); // Add Hitobject stuff foreach (HitObject ho in beatmap.HitObjects) { if (ho.IsSlider) // SliderVelocity changes { TimingPoint tp = ho.TimingPoint.Copy(); tp.Offset = ho.Time; tp.MpB = ho.SliderVelocity; timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true)); } } // Add the new SliderVelocity changes TimingPointsChange.ApplyChanges(timing, timingPointsChanges); // Save the file editor.SaveFile(); } // Complete progressbar if (worker != null && worker.WorkerReportsProgress) { worker.ReportProgress(100); } // Do stuff if (arg.Quick) { RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, reader != null)); } // Make an accurate message string message = ""; if (Math.Abs(slidersCompleted) == 1) { message += "Successfully completed " + slidersCompleted + " slider!"; } else { message += "Successfully completed " + slidersCompleted + " sliders!"; } return(arg.Quick ? "" : message); }
private string Complete_Sliders(Arguments arg, BackgroundWorker worker, DoWorkEventArgs _) { int slidersCompleted = 0; bool editorRead = EditorReaderStuff.TryGetFullEditorReader(out var reader); foreach (string path in arg.Paths) { var editor = EditorReaderStuff.GetBeatmapEditor(path, reader, editorRead, out var selected, out var editorActuallyRead); if (arg.SelectionMode == 0 && !editorActuallyRead) { return(EditorReaderStuff.SelectedObjectsReadFailText); } Beatmap beatmap = editor.Beatmap; Timing timing = beatmap.BeatmapTiming; List <HitObject> markedObjects = arg.SelectionMode == 0 ? selected : arg.SelectionMode == 1 ? beatmap.GetBookmarkedObjects() : beatmap.HitObjects; for (int i = 0; i < markedObjects.Count; i++) { HitObject ho = markedObjects[i]; if (ho.IsSlider) { double oldSpatialLength = ho.PixelLength; double newSpatialLength = arg.SpatialLength != -1 ? ho.GetSliderPath(fullLength: true).Distance *arg.SpatialLength : oldSpatialLength; double oldTemporalLength = timing.CalculateSliderTemporalLength(ho.Time, ho.PixelLength); double newTemporalLength = arg.TemporalLength != -1 ? timing.GetMpBAtTime(ho.Time) * arg.TemporalLength : oldTemporalLength; double oldSv = timing.GetSvAtTime(ho.Time); double newSv = oldSv / ((newSpatialLength / oldSpatialLength) / (newTemporalLength / oldTemporalLength)); ho.SliderVelocity = newSv; ho.PixelLength = newSpatialLength; // Scale anchors to completion if (arg.MoveAnchors) { ho.SetAllCurvePoints(SliderPathUtil.MoveAnchorsToLength( ho.GetAllCurvePoints(), ho.SliderType, ho.PixelLength, out var pathType)); ho.SliderType = pathType; } slidersCompleted++; } if (worker != null && worker.WorkerReportsProgress) { worker.ReportProgress(i / markedObjects.Count); } } // Reconstruct SliderVelocity List <TimingPointsChange> timingPointsChanges = new List <TimingPointsChange>(); // Add Hitobject stuff foreach (HitObject ho in beatmap.HitObjects) { if (ho.IsSlider) // SliderVelocity changes { TimingPoint tp = ho.TimingPoint.Copy(); tp.Offset = ho.Time; tp.MpB = ho.SliderVelocity; timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true)); } } // Add the new SliderVelocity changes TimingPointsChange.ApplyChanges(timing, timingPointsChanges); // Save the file editor.SaveFile(); } // Complete progressbar if (worker != null && worker.WorkerReportsProgress) { worker.ReportProgress(100); } // Do stuff if (arg.Quick) { RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, editorRead)); } // Make an accurate message string message = ""; if (Math.Abs(slidersCompleted) == 1) { message += "Successfully completed " + slidersCompleted + " slider!"; } else { message += "Successfully completed " + slidersCompleted + " sliders!"; } return(arg.Quick ? "" : message); }