Esempio n. 1
0
 public static bool ApproximatelyEquivalent(Vector3 a, Vector3 b, float tolerance)
 {
     return
         (MathHelper.ApproximatelyEquivalent(a.X, b.X, tolerance) &&
          MathHelper.ApproximatelyEquivalent(a.Y, b.Y, tolerance) &&
          MathHelper.ApproximatelyEquivalent(a.Z, b.Z, tolerance));
 }
Esempio n. 2
0
        private bool CheckMpB(double mpbNew, List <Marker> markers, TimingPoint redline, Arguments arg)
        {
            // For each their beatsFromRedline must stay the same AND their time must be within leniency of their resnapped time
            // If any of these times becomes incompatible, place a new anchor on the last time and not change the previous redline
            double mpbOld           = redline.MpB;
            double beatsFromRedline = 0;
            bool   canChangeRedline = true;

            foreach (Marker markerB in markers)
            {
                double timeB = markerB.Time;
                beatsFromRedline += markerB.BeatsFromLastMarker;

                // Get the beatsFromRedline after changing mpb
                redline.MpB = mpbNew;
                double resnappedTimeBA    = redline.Offset + redline.MpB * beatsFromRedline;
                double beatsFromRedlineBA = (resnappedTimeBA - redline.Offset) / redline.MpB;

                // Change MpB back so the redline doesn't get changed
                redline.MpB = mpbOld;

                // Check changes
                if (MathHelper.ApproximatelyEquivalent(beatsFromRedlineBA, beatsFromRedline, 0.1) && IsSnapped(timeB, resnappedTimeBA, arg.Leniency))
                {
                    continue;
                }
                canChangeRedline = false;
            }
            return(canChangeRedline);
        }
Esempio n. 3
0
        /// <summary>
        /// Get the angle in degrees between two points, clockwise from a to b
        /// when looking against the direction of the normal.
        /// </summary>
        /// <param name="a">The starting point.</param>
        /// <param name="b">The ending point.</param>
        /// <param name="normal">The normal of the points' face.</param>
        /// <returns>The angle between a and b, in degrees.</returns>
        public static double GetClockwiseAngle(Vector3 a, Vector3 b, Vector3 normal)
        {
            double result = Double.NaN;

            double angle = SignedAngleBetweenVectors(a, b, normal);

            if (angle > 0.0 || MathHelper.ApproximatelyEquivalent(angle, -180.0, 0.001))
            {
                result = angle;
            }

            return(result);
        }
Esempio n. 4
0
        public static Vector3 Intersect(Plane a, Plane b, Plane c)
        {
            float denominator = Vector3.Dot(a.Normal, Vector3.Cross(b.Normal, c.Normal));

            // Planes do not intersect.
            if (MathHelper.ApproximatelyEquivalent(denominator, 0.0f, 0.0001f))
            {
                return(new Vector3(Single.NaN));
            }

            var crossAB = Vector3.Cross(a.Normal, b.Normal);

            crossAB *= c.DistanceFromOrigin;

            var crossBC = Vector3.Cross(b.Normal, c.Normal);

            crossBC *= a.DistanceFromOrigin;

            var crossCA = Vector3.Cross(c.Normal, a.Normal);

            crossCA *= b.DistanceFromOrigin;

            return(new Vector3(crossBC + crossCA + crossAB) / denominator);
        }
Esempio n. 5
0
        private string Adjust_Timing(Arguments arg, BackgroundWorker worker, DoWorkEventArgs _)
        {
            // Count
            int RedlinesAdded = 0;

            bool editorRead = EditorReaderStuff.TryGetFullEditorReader(out var reader);

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

                // Get all the times to snap
                List <Marker> markers = new List <Marker>();
                if (arg.Objects)
                {
                    foreach (HitObject ho in beatmap.HitObjects)
                    {
                        markers.Add(new Marker(ho.Time));
                    }
                }
                if (arg.Bookmarks)
                {
                    foreach (double time in beatmap.GetBookmarks())
                    {
                        markers.Add(new Marker(time));
                    }
                }
                if (arg.Greenlines)
                {
                    // Get the offsets of greenlines
                    foreach (TimingPoint tp in timing.TimingPoints)
                    {
                        if (tp.Uninherited == false)
                        {
                            markers.Add(new Marker(tp.Offset));
                        }
                    }
                }
                if (arg.Redlines)
                {
                    // Get the offsets of redlines
                    foreach (TimingPoint tp in timing.TimingPoints)
                    {
                        if (tp.Uninherited == true)
                        {
                            markers.Add(new Marker(tp.Offset));
                        }
                    }
                }

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

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

                // 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
                for (int i = 0; i < markers.Count; i++)
                {
                    Marker marker = markers[i];
                    double time   = marker.Time;

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

                    // Resnap to that redline only
                    double resnappedTime = timing.Resnap(time, arg.Snap1, arg.Snap2, false, redline);

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

                    // Avoid problems
                    if (MathHelper.ApproximatelyEquivalent(beatsFromRedline, 0, 0.0001))
                    {
                        beatsFromRedline = 1 / Math.Max(arg.Snap1, arg.Snap2);
                    }
                    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.Snap1, arg.Snap2, false);

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

                        // Avoid problems
                        if (MathHelper.ApproximatelyEquivalent(beatsFromLastMarker, 0, 0.0001))
                        {
                            beatsFromLastMarker = 1f / Math.Max(arg.Snap1, arg.Snap2);
                        }
                        if (lastTime == time)
                        {
                            beatsFromLastMarker = 0;
                        }
                    }

                    // Set the variable
                    marker.BeatsFromLastMarker = beatsFromLastMarker;
                }

                // Remove redlines except the first redline
                if (!arg.Redlines)
                {
                    var first = timing.TimingPoints.FirstOrDefault(o => o.Uninherited);
                    timing.TimingPoints.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 = arg.BeatsBetween != -1 ? arg.BeatsBetween : 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.TimingPoints.Add(newRedline);
                        timing.Sort();

                        // 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);
            }

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

            message += RedlinesAdded;
            if (Math.Abs(RedlinesAdded) == 1)
            {
                message += " redlines!";
            }
            else
            {
                message += " redlines!";
            }
            return(message);
        }
        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);
        }
Esempio n. 7
0
 /// <summary>
 /// Approximates equivalence between two double-precision floating-point numbers on a direct human scale.
 /// It is important to note that this does not approximate equality - instead, it merely checks whether or not
 /// two numbers could be considered equivalent to each other within a certain tolerance. The tolerance is
 /// inclusive.
 /// </summary>
 /// <param name="a">The first value to compare.</param>
 /// <param name="b">The second value to compare.</param>
 /// <param name="tolerance">The tolerance within which the two values would be considered equivalent.</param>
 /// <returns>Whether or not the values can be considered equivalent within the tolerance.</returns>
 public static bool ApproximatelyEquivalent(double a, double b, double tolerance) => MathHelper.ApproximatelyEquivalent(a, b, tolerance);
Esempio n. 8
0
 /// <summary>
 /// Approximates equivalence between two single-precision floating-point numbers on a direct human scale.
 /// It is important to note that this does not approximate equality - instead, it merely checks whether or not
 /// two numbers could be considered equivalent to each other within a certain tolerance. The tolerance is
 /// inclusive.
 /// </summary>
 /// <param name="a">The first value to compare.</param>
 /// <param name="b">The second value to compare.</param>
 /// <param name="tolerance">The tolerance within which the two values would be considered equivalent.</param>
 /// <returns>Whether or not the values can be considered equivalent within the tolerance.</returns>
 public static bool ApproximatelyEquivalent(float a, float b, float tolerance) => MathHelper.ApproximatelyEquivalent(a, b, tolerance);