private string Adjust_Timing(TimingHelperVm arg, BackgroundWorker worker, DoWorkEventArgs _)
        {
            // Count
            int redlinesAdded = 0;

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();

            foreach (string path in arg.Paths)
            {
                // Open beatmap
                var     editor  = EditorReaderStuff.GetNewestVersionOrNot(path, reader);
                Beatmap beatmap = editor.Beatmap;
                Timing  timing  = beatmap.BeatmapTiming;

                // Get all the times to snap
                List <Marker> markers = new List <Marker>();
                if (arg.Objects)
                {
                    markers.AddRange(beatmap.HitObjects.Select(ho => new Marker(ho.Time)));
                }
                if (arg.Bookmarks)
                {
                    markers.AddRange(beatmap.GetBookmarks().Select(time => new Marker(time)));
                }
                if (arg.Greenlines)
                {
                    // Get the offsets of greenlines
                    markers.AddRange(from tp in timing.TimingPoints where !tp.Uninherited select new Marker(tp.Offset));
                }
                if (arg.Redlines)
                {
                    // Get the offsets of redlines
                    markers.AddRange(from tp in timing.TimingPoints where tp.Uninherited select new Marker(tp.Offset));
                }

                // Update progressbar
                if (worker != null && worker.WorkerReportsProgress)
                {
                    worker.ReportProgress(20);
                }

                // Sort the markers
                markers = markers.OrderBy(o => o.Time).ToList();

                // If there are no redlines add one with a default BPM
                if (!timing.TimingPoints.Any(tp => tp.Uninherited))
                {
                    timing.Add(new TimingPoint(0, 1000, 4, SampleSet.Soft, 0, 100, true, false, false));
                }

                // Remove multiple markers on the same tick
                var newMarkers = new List <Marker>(markers.Count);
                newMarkers.AddRange(markers.Where((t, i) => i == 0 || Math.Abs(t.Time - markers[i - 1].Time) >= arg.Leniency + Precision.DOUBLE_EPSILON));
                markers = newMarkers;

                // Calculate the beats between time and the last time or redline for each time
                // Time the same is 0
                // Time a little after is smallest snap
                foreach (var marker in markers)
                {
                    double time = marker.Time;

                    TimingPoint redline = timing.GetRedlineAtTime(time - 1);

                    // Resnap to that redline only
                    double resnappedTime = timing.Resnap(time, arg.BeatDivisors, false, tp: redline);

                    // Calculate beats from the redline
                    double beatsFromRedline = (resnappedTime - redline.Offset) / redline.MpB;

                    // Avoid problems
                    if (MathHelper.ApproximatelyEquivalent(beatsFromRedline, 0, 0.0001))
                    {
                        beatsFromRedline = arg.BeatDivisors.Min(o => o.GetValue());
                    }
                    if (time == redline.Offset)
                    {
                        beatsFromRedline = 0;
                    }

                    // Initialize the beats from last marker
                    double beatsFromLastMarker = beatsFromRedline;

                    // Get the times between redline and this time
                    List <Marker> timesBefore = markers.Where(o => o.Time <time && o.Time> redline.Offset).ToList();

                    if (timesBefore.Count > 0)
                    {
                        // Get the last time info
                        double lastTime       = timesBefore.Last().Time;
                        double resnappedTimeL = timing.Resnap(lastTime, arg.BeatDivisors, false);

                        // Change the beats from last marker
                        beatsFromLastMarker = (resnappedTime - resnappedTimeL) / redline.MpB;

                        // Avoid problems
                        if (MathHelper.ApproximatelyEquivalent(beatsFromLastMarker, 0, 0.0001))
                        {
                            beatsFromLastMarker = arg.BeatDivisors.Min(o => o.GetValue());
                        }
                        if (lastTime == time)
                        {
                            beatsFromLastMarker = 0;
                        }
                    }

                    // Set the variable
                    marker.BeatsFromLastMarker = beatsFromLastMarker;

                    if (arg.BeatsBetween != -1)
                    {
                        marker.BeatsFromLastMarker = arg.BeatsBetween;
                    }
                }

                // Remove redlines except the first redline
                if (!arg.Redlines)
                {
                    var first = timing.TimingPoints.FirstOrDefault(o => o.Uninherited);
                    timing.RemoveAll(o => o.Uninherited && o != first);
                }

                // Update progressbar
                if (worker != null && worker.WorkerReportsProgress)
                {
                    worker.ReportProgress(40);
                }

                // Loop through all the markers
                for (int i = 0; i < markers.Count; i++)
                {
                    Marker marker = markers[i];
                    double time   = marker.Time;

                    TimingPoint redline = timing.GetRedlineAtTime(time - 1);

                    double beatsFromLastMarker = marker.BeatsFromLastMarker;

                    // Skip if 0 beats from last marker
                    if (beatsFromLastMarker == 0)
                    {
                        continue;
                    }

                    // Get the times between redline and this time including this time
                    List <Marker> markersBefore = markers.Where(o => o.Time <time && o.Time> redline.Offset).ToList();
                    markersBefore.Add(marker);

                    // Calculate MpB
                    // Average MpB from timesBefore and use time from redline
                    double mpb = 0;
                    double beatsFromRedline = 0;
                    foreach (Marker markerB in markersBefore)
                    {
                        beatsFromRedline += markerB.BeatsFromLastMarker;
                        mpb += GetMpB(markerB.Time - redline.Offset, beatsFromRedline, 0);
                    }
                    mpb /= markersBefore.Count;

                    // Check if this MpB doesn't make the markers go offsnap too far
                    bool canChangeRedline = CheckMpB(mpb, markersBefore, redline, arg);

                    // Make changes
                    if (canChangeRedline)
                    {
                        // Round the MpB to human values first
                        mpb = HumanRoundMpB(mpb, markersBefore, redline, arg);

                        // Change the MpB of the redline
                        redline.MpB = mpb;
                    }
                    else
                    {
                        // Get the last time info and not the current
                        markersBefore.Remove(marker);
                        double lastTime = markersBefore.Last().Time;

                        // Make new redline
                        TimingPoint newRedline    = redline.Copy();
                        TimingPoint lastHitsounds = timing.GetTimingPointAtTime(lastTime + 5);
                        newRedline.Offset           = lastTime;
                        newRedline.OmitFirstBarLine = arg.OmitBarline; // Set omit to the argument
                        newRedline.Kiai             = lastHitsounds.Kiai;
                        newRedline.SampleIndex      = lastHitsounds.SampleIndex;
                        newRedline.SampleSet        = lastHitsounds.SampleSet;
                        newRedline.Volume           = lastHitsounds.Volume;
                        timing.Add(newRedline);

                        // Set the MpB
                        newRedline.MpB = GetMpB(time - lastTime, beatsFromLastMarker, arg.Leniency);

                        // Update the counter
                        redlinesAdded++;
                    }

                    // Update progressbar
                    if (worker != null && worker.WorkerReportsProgress)
                    {
                        worker.ReportProgress(i * 60 / markers.Count + 40);
                    }
                }

                // Save the file
                editor.SaveFile();
            }


            // Complete progressbar
            if (worker != null && worker.WorkerReportsProgress)
            {
                worker.ReportProgress(100);
            }

            // Do QuickRun stuff
            RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, reader != null, arg.Quick));

            // Make an accurate message
            string message = "Successfully added ";

            message += redlinesAdded;
            if (Math.Abs(redlinesAdded) == 1)
            {
                message += " redlines!";
            }
            else
            {
                message += " redlines!";
            }

            return(arg.Quick ? string.Empty : message);
        }
Example #2
0
    bool FindSyncPoint(Music.SyncType syncType, int syncFactor, int currentSample, int entryPointSample, out int syncPointSample)
    {
        syncPointSample = currentSample;

        MusicMeterBySample currentMeter  = GetMeterFromSample(currentSample);
        Timing             currentTiming = currentMeter != null?currentMeter.GetTimingFromSample(currentSample) : new Timing();

        Timing syncPointCandidateTiming = new Timing(currentTiming);

        switch (syncType)
        {
        case Music.SyncType.Immediate:
            syncPointSample = currentSample + entryPointSample;
            break;

        case Music.SyncType.ExitPoint:
            syncPointSample = CurrentSection.ExitPointSample;
            if (syncPointSample <= currentSample + entryPointSample)
            {
                return(false);
            }
            break;

        case Music.SyncType.Bar:
            syncPointCandidateTiming.Set(currentTiming.Bar - (currentTiming.Bar - currentMeter.StartBar) % syncFactor + syncFactor, 0, 0);
            syncPointSample = CurrentSection.GetSampleFromTiming(syncPointCandidateTiming);
            while (syncPointSample <= currentSample + entryPointSample)
            {
                syncPointCandidateTiming.Add(syncFactor);
                if (syncPointCandidateTiming > CurrentSection.ExitPointTiming)
                {
                    return(false);
                }
                syncPointSample = CurrentSection.GetSampleFromTiming(syncPointCandidateTiming);
            }
            break;

        case Music.SyncType.Beat:
            syncPointCandidateTiming.Set(currentTiming.Bar, currentTiming.Beat - (currentTiming.Beat % syncFactor) + syncFactor, 0);
            syncPointCandidateTiming.Fix(currentMeter);
            syncPointSample = CurrentSection.GetSampleFromTiming(syncPointCandidateTiming);
            while (syncPointSample <= currentSample + entryPointSample)
            {
                syncPointCandidateTiming.Add(0, syncFactor, 0, currentMeter);
                syncPointCandidateTiming.Fix(currentMeter);
                if (syncPointCandidateTiming > CurrentSection.ExitPointTiming)
                {
                    return(false);
                }
                currentMeter    = GetMeterFromTiming(syncPointCandidateTiming);
                syncPointSample = CurrentSection.GetSampleFromTiming(syncPointCandidateTiming);
            }
            break;

        case Music.SyncType.Unit:
            syncPointCandidateTiming.Set(currentTiming.Bar, currentTiming.Beat, currentTiming.Unit - (currentTiming.Unit % syncFactor) + syncFactor);
            syncPointCandidateTiming.Fix(currentMeter);
            syncPointSample = CurrentSection.GetSampleFromTiming(syncPointCandidateTiming);
            while (syncPointSample <= currentSample + entryPointSample)
            {
                syncPointCandidateTiming.Add(0, 0, syncFactor, currentMeter);
                syncPointCandidateTiming.Fix(currentMeter);
                if (syncPointCandidateTiming > CurrentSection.ExitPointTiming)
                {
                    return(false);
                }
                currentMeter    = GetMeterFromTiming(syncPointCandidateTiming);
                syncPointSample = CurrentSection.GetSampleFromTiming(syncPointCandidateTiming);
            }
            break;

        case Music.SyncType.Marker:
            if (0 <= syncFactor && syncFactor < CurrentSection.Markers.Length && CurrentSection.Markers[syncFactor].Timings.Length > 0)
            {
                MusicSection.MusicMarker marker = CurrentSection.Markers[syncFactor];
                int markerIndex = 0;
                syncPointCandidateTiming.Set(marker.Timings[markerIndex]);

                syncPointSample = CurrentSection.GetSampleFromTiming(syncPointCandidateTiming);
                while (syncPointSample <= currentSample + entryPointSample)
                {
                    ++markerIndex;
                    if (marker.Timings.Length <= markerIndex)
                    {
                        return(false);
                    }
                    syncPointCandidateTiming.Set(marker.Timings[markerIndex]);
                    syncPointSample = CurrentSection.GetSampleFromTiming(syncPointCandidateTiming);
                }
            }
            else
            {
                print(String.Format("Failed to SetNextSection. {0} section doesn't have Marker[{1}].", CurrentSection.Name, syncFactor));
                return(false);
            }
            break;
        }
        return(true);
    }
        private string Copy_Timing(TimingCopierVm arg, BackgroundWorker worker, DoWorkEventArgs _)
        {
            string[] paths    = arg.ExportPath.Split('|');
            int      mapsDone = 0;

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();

            foreach (string exportPath in paths)
            {
                var editorTo   = EditorReaderStuff.GetNewestVersionOrNot(exportPath, reader);
                var editorFrom = EditorReaderStuff.GetNewestVersionOrNot(arg.ImportPath, reader);

                Beatmap beatmapTo   = editorTo.Beatmap;
                Beatmap beatmapFrom = editorFrom.Beatmap;

                Timing timingTo   = beatmapTo.BeatmapTiming;
                Timing timingFrom = beatmapFrom.BeatmapTiming;

                // Get markers for hitobjects if mode 1 is used
                List <Marker> markers = new List <Marker>();
                if (arg.ResnapMode == "Number of beats between objects stays the same")
                {
                    markers = GetMarkers(beatmapTo, timingTo);
                }

                // Rid the beatmap of redlines
                // If a greenline exists at the same time as a redline then the redline ceizes to exist
                // Else convert the redline to a greenline: Inherited = false & MpB = -100
                List <TimingPoint> removeList = new List <TimingPoint>();
                foreach (TimingPoint redline in timingTo.Redlines)
                {
                    TimingPoint greenlineHere = timingTo.GetGreenlineAtTime(redline.Offset);

                    if (greenlineHere.Offset != redline.Offset)
                    {
                        var newGreenline = redline.Copy();
                        newGreenline.Uninherited = false;
                        newGreenline.MpB         = -100;

                        timingTo.Add(newGreenline);
                    }

                    removeList.Add(redline);
                }
                foreach (TimingPoint tp in removeList)
                {
                    timingTo.Remove(tp);
                }

                // Make new timing points changes
                List <TimingPointsChange> timingPointsChanges = new List <TimingPointsChange>();

                // Add redlines
                var redlines = timingFrom.Redlines;
                foreach (TimingPoint tp in redlines)
                {
                    timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true, meter: true, unInherited: true, omitFirstBarLine: true, fuzzyness: Precision.DOUBLE_EPSILON));
                }

                // Apply timing changes
                TimingPointsChange.ApplyChanges(timingTo, timingPointsChanges);

                if (arg.ResnapMode == "Number of beats between objects stays the same")
                {
                    redlines = timingTo.Redlines;
                    List <double> newBookmarks = new List <double>();
                    double        lastTime     = redlines.FirstOrDefault().Offset;
                    foreach (Marker marker in markers)
                    {
                        // Get redlines between this and last marker
                        TimingPoint redline = timingTo.GetRedlineAtTime(lastTime, redlines.FirstOrDefault());

                        double beatsFromLastTime = marker.BeatsFromLastMarker;
                        while (true)
                        {
                            List <TimingPoint> redlinesBetween = redlines.Where(o => o.Offset <= lastTime + redline.MpB * beatsFromLastTime && o.Offset > lastTime).ToList();

                            if (redlinesBetween.Count == 0)
                            {
                                break;
                            }

                            TimingPoint first = redlinesBetween.First();
                            double      diff  = first.Offset - lastTime;
                            beatsFromLastTime -= diff / redline.MpB;

                            redline  = first;
                            lastTime = first.Offset;
                        }

                        // Last time is the time of the last redline in between
                        double newTime = lastTime + redline.MpB * beatsFromLastTime;
                        newTime     = timingTo.Resnap(newTime, arg.BeatDivisors, firstTp: redlines.FirstOrDefault());
                        marker.Time = newTime;

                        lastTime = marker.Time;
                    }

                    // Add the bookmarks
                    foreach (Marker marker in markers)
                    {
                        // Check whether the marker is a bookmark
                        if (marker.Object is double)
                        {
                            // Don't resnap bookmarks
                            newBookmarks.Add((double)marker.Object);
                        }
                    }
                    beatmapTo.SetBookmarks(newBookmarks);
                }
                else if (arg.ResnapMode == "Just resnap")
                {
                    // Resnap hitobjects
                    foreach (HitObject ho in beatmapTo.HitObjects)
                    {
                        ho.ResnapSelf(timingTo, arg.BeatDivisors, firstTp: redlines.FirstOrDefault());
                        ho.ResnapEnd(timingTo, arg.BeatDivisors, firstTp: redlines.FirstOrDefault());
                    }

                    // Resnap greenlines
                    foreach (TimingPoint tp in timingTo.Greenlines)
                    {
                        tp.ResnapSelf(timingTo, arg.BeatDivisors, firstTP: redlines.FirstOrDefault());
                    }
                    timingTo.Sort();
                }
                else
                {
                    // Don't move objects
                }

                // Save the file
                editorTo.SaveFile();

                // Update progressbar
                if (worker != null && worker.WorkerReportsProgress)
                {
                    worker.ReportProgress(++mapsDone * 100 / paths.Length);
                }
            }

            // Make an accurate message
            string message = $"Successfully copied timing to {mapsDone} {(mapsDone == 1 ? "beatmap" : "beatmaps")}!";

            return(message);
        }
Example #4
0
        public void AddChange(Timing timing, bool allAfter = false)
        {
            TimingPoint        addingTimingPoint = null;
            TimingPoint        prevTimingPoint   = null;
            List <TimingPoint> onTimingPoints    = new List <TimingPoint>();
            bool onHasRed   = false;
            bool onHasGreen = false;

            foreach (TimingPoint tp in timing)
            {
                if (tp == null)
                {
                    continue;
                }                              // Continue nulls to avoid exceptions
                if (tp.Offset < MyTP.Offset && (prevTimingPoint == null || tp.Offset >= prevTimingPoint.Offset))
                {
                    prevTimingPoint = tp;
                }
                if (Math.Abs(tp.Offset - MyTP.Offset) <= Fuzzyness)
                {
                    onTimingPoints.Add(tp);
                    onHasRed   = tp.Uninherited || onHasRed;
                    onHasGreen = !tp.Uninherited || onHasGreen;
                }
            }

            if (onTimingPoints.Count > 0)
            {
                prevTimingPoint = onTimingPoints.Last();
            }

            if (UnInherited && !onHasRed)
            {
                // Make new redline
                if (prevTimingPoint == null)
                {
                    addingTimingPoint             = MyTP.Copy();
                    addingTimingPoint.Uninherited = true;
                }
                else
                {
                    addingTimingPoint             = prevTimingPoint.Copy();
                    addingTimingPoint.Offset      = MyTP.Offset;
                    addingTimingPoint.Uninherited = true;
                }
                onTimingPoints.Add(addingTimingPoint);
            }
            if (!UnInherited && (onTimingPoints.Count == 0 || (MpB && !onHasGreen)))
            {
                // Make new greenline (based on prev)
                if (prevTimingPoint == null)
                {
                    addingTimingPoint             = MyTP.Copy();
                    addingTimingPoint.Uninherited = false;
                }
                else
                {
                    addingTimingPoint             = prevTimingPoint.Copy();
                    addingTimingPoint.Offset      = MyTP.Offset;
                    addingTimingPoint.Uninherited = false;
                    if (prevTimingPoint.Uninherited)
                    {
                        addingTimingPoint.MpB = -100;
                    }
                }
                onTimingPoints.Add(addingTimingPoint);
            }

            foreach (TimingPoint on in onTimingPoints)
            {
                if (MpB && (UnInherited ? on.Uninherited : !on.Uninherited))
                {
                    on.MpB = MyTP.MpB;
                }
                if (Meter && UnInherited && on.Uninherited)
                {
                    on.Meter = MyTP.Meter;
                }
                if (Sampleset)
                {
                    on.SampleSet = MyTP.SampleSet;
                }
                if (Index)
                {
                    on.SampleIndex = MyTP.SampleIndex;
                }
                if (Volume)
                {
                    on.Volume = MyTP.Volume;
                }
                if (Kiai)
                {
                    on.Kiai = MyTP.Kiai;
                }
                if (OmitFirstBarLine && UnInherited && on.Uninherited)
                {
                    on.OmitFirstBarLine = MyTP.OmitFirstBarLine;
                }
            }

            if (addingTimingPoint != null && (prevTimingPoint == null || !addingTimingPoint.SameEffect(prevTimingPoint) || UnInherited))
            {
                timing.Add(addingTimingPoint);
            }

            if (allAfter) // Change every timingpoint after
            {
                foreach (TimingPoint tp in timing)
                {
                    if (tp.Offset > MyTP.Offset)
                    {
                        if (Sampleset)
                        {
                            tp.SampleSet = MyTP.SampleSet;
                        }
                        if (Index)
                        {
                            tp.SampleIndex = MyTP.SampleIndex;
                        }
                        if (Volume)
                        {
                            tp.Volume = MyTP.Volume;
                        }
                        if (Kiai)
                        {
                            tp.Kiai = MyTP.Kiai;
                        }
                    }
                }
            }
        }