Beispiel #1
0
        public BeatmapInfo(string filename)
        {
            List <Note>     notes;
            List <LongNote> lns;

            //  Load, and parse.
            if (File.Exists(filename))
            {
                if (filename.Split('.')[filename.Split('.').Length - 1] != "osu")
                {
                    throw new InvalidBeatmapException("Unknown file format.");
                }

                Data = MetadataParser.Parse(filename);
                HitObjectParser.Parse(filename, out notes, out lns, Data.Keys);
            }
            else
            {
                throw new FileNotFoundException();
            }

            //  Calculate densities.
            JenksDensity = DensityCalculator.GetJenksDensity(ref notes, ref lns, Data.Keys);
            JenksSpeed   = DensityCalculator.GetJenksSpeed(ref notes, ref lns);

            //  Copy data.
            Notes = notes;
            LNs   = lns;
        }
Beispiel #2
0
        protected override int[] GetTickLocations()
        {
            double length = Math.Round(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture), 4);

            int sliderruns = Int32.Parse(HitObjectParser.GetProperty(id, "repeat"));
            //Only need ticks for one slider length (no repeats needed)
            //Also no need for double conversion since TickCount is always divisible by sliderruns
            int tickcount = this.GetTickCount() / sliderruns;

            double slidervelocity = this.GetSliderVelocity();
            double tickrate       = Double.Parse(map.GetTag("Difficulty", "SliderTickRate"), CultureInfo.InvariantCulture);
            double ticklength     = Math.Round(slidervelocity * (100 / tickrate), 4);

            if (length <= ticklength)
            {
                return(new int[0]);
            }

            Point[] ticklocs = curve.GetTickLocations(ticklength, tickcount);

            List <int> xcoords = new List <int>();

            foreach (Point i in ticklocs)
            {
                xcoords.Add(i.IntX());
            }

            return(xcoords.ToArray());
        }
Beispiel #3
0
        public BeatmapInfo(string filename)
        {
            List <Note>     notes;
            List <LongNote> lns;

            //  Load, and parse.
            if (File.Exists(filename))
            {
                if (filename.Split('.')[filename.Split('.').Length - 1] != "osu")
                {
                    throw new InvalidBeatmapException("Unknown file format.");
                }

                Data = MetadataParser.Parse(filename);
                HitObjectParser.Parse(filename, out notes, out lns, Data.Keys);
            }
            else
            {
                throw new FileNotFoundException();
            }

            //  Calculate densities.
            var orgDen = DensityCalculator.GetDensity(ref notes, ref lns);
            var corDen = DensityCalculator.GetCorrectedDensity(ref notes, ref lns, Data.Keys);

            //  Copy data.
            Notes = notes;
            LNs   = lns;

            MaxDen    = orgDen.Item1;
            AvgDen    = orgDen.Item2;
            CorMaxDen = corDen.Item1;
            CorAvgDen = corDen.Item2;
        }
Beispiel #4
0
        protected override int[] GetTickLocations()
        {
            double length = Math.Round(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture), 4);

            double slidervelocity = this.GetSliderVelocity();
            double tickrate       = Double.Parse(map.GetTag("Difficulty", "SliderTickRate"), CultureInfo.InvariantCulture);
            double ticklength     = Math.Round(slidervelocity * (100 / tickrate), 4);

            if (length <= ticklength)
            {
                return(new int[0]);
            }

            List <int> ticks = new List <int>();

            //Will represent where the next tick is in the slider
            double calclength = ticklength;

            //While we haven't fallen off the end of the slider
            while (calclength < length)
            {
                ticks.Add(curve.GetPointAlong(calclength).IntX());
                //Move down the slider by a ticklength
                calclength += ticklength;
            }

            return(ticks.ToArray());
        }
Beispiel #5
0
        //Calculates the Milliseconds per Beat at a specified time by searching
        //through the entire timing points section
        //Timing points inside sliders don't affect the slider itself
        protected double GetMpB()
        {
            int ms = Int32.Parse(HitObjectParser.GetProperty(id, "time"));

            //Get all the timing sections of the beatmap
            string[] timings = this.map.GetSection("TimingPoints");
            //Will hold the relevant timing point
            string timingpoint = null;
            //Store the index of the timing point just in case we need to iterate backwards later
            int index;

            //Find the section that applies to the given time
            for (index = 0; index < timings.Length; index++)
            {
                //Split the string by commas to get all the relevant times
                string[] attributes = timings[index].Split(',');
                //Trim each string just in case
                attributes = LibFuncs.TrimStringArray(attributes);
                //If the timing point is a higher time, then we want the previous timing section
                if (Double.Parse(attributes[0]) > ms)
                {
                    //avoid accessing a negative timing point
                    if (index == 0)
                    {
                        timingpoint = timings[0];
                    }
                    else
                    {
                        timingpoint = timings[index - 1];
                    }
                    break;
                }
            }

            //If the timing point needed is the very last one
            if (timingpoint == null)
            {
                timingpoint = timings[timings.Length - 1];
            }

            //If the mpb is negative, then we need to search backwards to find a positive one
            if (Double.Parse(timingpoint.Split(',')[1], CultureInfo.InvariantCulture) < 0)
            {
                for (int i = index - 1; i >= 0; i--)
                {
                    //Split the string by commas to get all the relevant times
                    string[] attributes = timings[i].Split(',');
                    //Trim each string just in case
                    attributes = LibFuncs.TrimStringArray(attributes);

                    if (Double.Parse(attributes[1]) > 0)
                    {
                        timingpoint = timings[i];
                        break;
                    }
                }
            }

            return(Double.Parse(timingpoint.Split(',')[1], CultureInfo.InvariantCulture));
        }
Beispiel #6
0
        protected override Point GetLastPoint()
        {
            //Necessary to avoid cases where the pixellength is something like 105.000004005432
            int length = Convert.ToInt32(Math.Floor(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture)));

            return(curve.GetPointAlong(length));
        }
Beispiel #7
0
        protected override int[] GetTickLocations()
        {
            //Necessary to avoid cases where the pixellength is something like 105.000004005432
            int length = Convert.ToInt32(Math.Floor(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture)));

            double slidervelocity = this.GetSliderVelocity();
            double tickrate       = Double.Parse(map.GetTag("Difficulty", "SliderTickRate"), CultureInfo.InvariantCulture);
            int    ticklength     = (int)Math.Round(slidervelocity * (100 / tickrate));

            if (length <= ticklength)
            {
                return(new int[0]);
            }

            List <int> ticks = new List <int>();

            //Will represent where the next tick is in the slider
            int calclength = ticklength;

            //While we haven't fallen off the end of the slider
            while (calclength < length)
            {
                ticks.Add(curve.GetPointAlong(calclength).IntX());
                //Move down the slider by a ticklength
                calclength += ticklength;
            }

            return(ticks.ToArray());
        }
Beispiel #8
0
        public CatmullSlider(string id, Beatmap amap) : base(id, amap)
        {
            Point initialcoord = new Point();

            initialcoord.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            initialcoord.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));

            curve = new CatmullCurve(initialcoord, this.controlpoints);
        }
Beispiel #9
0
        public int[] GetHitLocations()
        {
            //There is only one hit location for a circle, so just return an array
            //that holds that hit location
            string loc = HitObjectParser.GetProperty(circleid, "X");

            return(new int[1] {
                Convert.ToInt32(loc)
            });
        }
Beispiel #10
0
        public int[] GetHitTimes()
        {
            //There is only one hit time for a circle, so just return an array
            //that holds that hit time
            string time = HitObjectParser.GetProperty(circleid, "time");

            return(new int[1] {
                Convert.ToInt32(time)
            });
        }
Beispiel #11
0
        //TODO: Throw error if somethings messed up with the timing section
        //Calculates the slider velocity at a specified time using the default
        //velocity and the relevant timing section
        //Timing points inside sliders don't affect the slider itself
        protected double GetSliderVelocity()
        {
            int ms = Int32.Parse(HitObjectParser.GetProperty(id, "time"));
            //Get the default slider velocity of the beatmap
            double slidervelocity = Double.Parse(map.GetTag("Difficulty", "SliderMultiplier"), CultureInfo.InvariantCulture);

            //Get all the timing sections of the beatmap
            string[] timings = this.map.GetSection("TimingPoints");
            //Will hold the relevant timing point
            string timingpoint = null;

            //Find the section that applies to the given time
            for (int i = 0; i < timings.Length; i++)
            {
                //Split the string by commas to get all the relevant times
                string[] attributes = timings[i].Split(',');
                //Trim each string just in case
                attributes = LibFuncs.TrimStringArray(attributes);
                //If the timing point is a higher time, then we want the previous timing section
                if (Double.Parse(attributes[0]) > ms)
                {
                    //avoid accessing a negative timing point
                    if (i == 0)
                    {
                        timingpoint = timings[0];
                    }
                    else
                    {
                        timingpoint = timings[i - 1];
                    }
                    break;
                }
            }

            //If the timing point needed is the very last one
            if (timingpoint == null)
            {
                timingpoint = timings[timings.Length - 1];
            }

            string[] properties = timingpoint.Split(',');
            //If the offset is positive, then there is no slider multiplication
            if (Double.Parse(properties[1], CultureInfo.InvariantCulture) > 0)
            {
                return(slidervelocity);
            }
            //Otherwise the slider multiplier is 100 / abs(offset)
            else
            {
                double offset = Double.Parse(properties[1], CultureInfo.InvariantCulture);
                return(slidervelocity * (100 / Math.Abs(offset)));
            }
        }
Beispiel #12
0
        private void handleGeneral(Sheetmusic sheetmusic, string line)        // general區塊
        {
            var pair = splitKeyVal(line, ':');

            var metadata = sheetmusic.SheetmusicInfo.Metadata;

            switch (pair.Key)
            {
            case @"AudioFilename":
                metadata.AudioFile = pair.Value;
                break;

            case @"AudioLeadIn":
                sheetmusic.SheetmusicInfo.AudioLeadIn = int.Parse(pair.Value);
                break;

            case @"PreviewTime":
                metadata.PreviewTime = int.Parse(pair.Value);
                break;

            //case @"Countdown":
            //    sheetmusic.SheetmusicInfo.Countdown = int.Parse(pair.Value) == 1;
            //    break;
            //case @"SampleSet":
            //    defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), pair.Value);
            //    break;
            //case @"SampleVolume":
            //    defaultSampleVolume = int.Parse(pair.Value);
            //    break;
            //case @"StackLeniency":
            //    beatmap.BeatmapInfo.StackLeniency = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo);
            //    break;
            case @"Mode":
                sheetmusic.SheetmusicInfo.RulesetID = int.Parse(pair.Value);

                switch (sheetmusic.SheetmusicInfo.RulesetID)
                {
                case 0:
                    parser = new Base.Rulesets.Straight.Rulesets.Objects.Parsers.ConvertHitObjectParser();
                    break;
                }
                break;
                //case @"LetterboxInBreaks":
                //    beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(pair.Value) == 1;
                //    break;
                //case @"SpecialStyle":
                //    beatmap.BeatmapInfo.SpecialStyle = int.Parse(pair.Value) == 1;
                //    break;
                //case @"WidescreenStoryboard":
                //    beatmap.BeatmapInfo.WidescreenStoryboard = int.Parse(pair.Value) == 1;
                //    break;
            }
        }
Beispiel #13
0
        //Get the correct type of hitobject to put into the hitobject variable
        public GenericHitObject(string id, Beatmap map)
        {
            HitObjectType objecttype = HitObjectParser.GetHitObjectType(id);

            if (objecttype == HitObjectType.Circle)
            {
                hitobject = new Circle(id);
            }
            else if (objecttype == HitObjectType.Slider)
            {
                string slidertype = HitObjectParser.GetProperty(id, "slidertype");
                if (slidertype == "L")
                {
                    hitobject = new LinearSlider(id, map);
                }
                //Special behavior is needed for passthrough sliders
                else if (slidertype == "P")
                {
                    //Treat the slider differently depending on the number of control points
                    string[] sliderpoints = HitObjectParser.GetProperty(id, "controlpoints").Split('|');
                    if (sliderpoints.Length == 1)
                    {
                        hitobject = new LinearSlider(id, map);
                    }
                    else if (sliderpoints.Length == 2)
                    {
                        hitobject = new PassthroughSlider(id, map);
                    }
                    else
                    {
                        hitobject = new BezierSlider(id, map);
                    }
                }
                else if (slidertype == "B")
                {
                    hitobject = new BezierSlider(id, map);
                }
                else if (slidertype == "C")
                {
                    hitobject = new CatmullSlider(id, map);
                }
            }
            else if (objecttype == HitObjectType.Spinner)
            {
                hitobject = new Spinner();
            }
            else
            {
                throw new ArgumentException("Error: id is invalid");
            }
        }
Beispiel #14
0
        //Constructs a slider given an id
        //The beatmap given is the beatmap that the slider resides in
        //Used to make calculations related to timing
        protected GenericSlider(string tempid, Beatmap amap)
        {
            id  = tempid;
            map = amap;

            //Checks that the hitobject given is actually a slider
            if (HitObjectParser.GetHitObjectType(id) != HitObjectType.Slider)
            {
                throw new ArgumentException("Hitobject provided to slider class is not a slider");
            }

            //Gets the control points of the slider in a formatted array of Points
            controlpoints = FormatControlPoints();
        }
Beispiel #15
0
        //Calculated the same regardless of slider type, but depends on GetTickLocations and GetLastPoint
        public int[] GetHitLocations()
        {
            List <int> hitpoints = new List <int>();
            List <int> ticklocs  = new List <int>();

            //Subtracting 1 returns the actual number of repeats
            int repeats = Int32.Parse(HitObjectParser.GetProperty(id, "repeat")) - 1;

            //Get the initial hit point of the slider
            //Split into three lines for readibility
            Point initialcoord = new Point();

            initialcoord.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            initialcoord.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));

            //Get the first and last x-coordinates of the slider
            int beginpoint = initialcoord.IntX();

            ticklocs.AddRange(this.GetTickLocations());
            int endpoint = this.GetLastPoint().IntX();

            hitpoints.Add(beginpoint);
            hitpoints.AddRange(ticklocs);
            hitpoints.Add(endpoint);

            if (repeats > 0)
            {
                for (int i = 1; i <= repeats; i++)
                {
                    ticklocs.Reverse();
                    hitpoints.AddRange(ticklocs);
                    /// Add the endpoint or the beginpoint depending on whether
                    /// the slider is going forwards or backwards (repeat is even
                    /// or odd)
                    //even
                    if (i % 2 == 0)
                    {
                        hitpoints.Add(endpoint);
                    }
                    //odd
                    else
                    {
                        hitpoints.Add(beginpoint);
                    }
                }
            }

            //Return the hitpoints
            return(hitpoints.ToArray());
        }
Beispiel #16
0
        public PassthroughSlider(string id, Beatmap amap) : base(id, amap)
        {
            if (controlpoints.Length != 2)
            {
                throw new ArgumentException("Error: Passthrough slider does not have 2 control points\n" +
                                            "controlpoints.Length=" + controlpoints.Length);
            }

            Point initialcoord = new Point();

            initialcoord.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            initialcoord.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));

            double length = Math.Round(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture), 4);

            curve = new CircleCurve(initialcoord, controlpoints[0], controlpoints[1], length);
        }
Beispiel #17
0
        //Uses the given list of control points to construct a list of curves
        //to account for red points
        public LinearSlider(string id, Beatmap amap) : base(id, amap)
        {
            //Get the initial hit point of the slider
            //Split into three lines for readibility
            Point initialcoord = new Point();

            initialcoord.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            initialcoord.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));

            //List<Point> curvepoints = new List<Point>();
            List <LinearCurve> accumulatedcurves = new List <LinearCurve>();

            //Normal linear slider
            if (controlpoints.Length == 1)
            {
                accumulatedcurves.Add(new LinearCurve(initialcoord, controlpoints[0]));
            }
            else
            {
                List <Point> allcontrolpoints = new List <Point>();

                //Add first point only if it's not repeated in the control points (old maps)
                if (initialcoord.IntX() != controlpoints[0].IntX() || initialcoord.IntY() != controlpoints[0].IntY())
                {
                    allcontrolpoints.Add(initialcoord);
                }
                allcontrolpoints.AddRange(controlpoints);

                Point[][] curvepoints = LibFuncs.SplitPointList(allcontrolpoints.ToArray());
                foreach (Point[] curve in curvepoints)
                {
                    if (curve.Length > 2)
                    {
                        for (int i = 1; i < curve.Length; i++)
                        {
                            accumulatedcurves.Add(new LinearCurve(curve[i - 1], curve[i]));
                        }
                    }
                    else
                    {
                        accumulatedcurves.Add(new LinearCurve(curve[0], curve[1]));
                    }
                }
            }
            curves = accumulatedcurves.ToArray();
        }
Beispiel #18
0
        protected override Point GetLastPoint()
        {
            //Necessary to avoid cases where the pixellength is something like 105.000004005432
            int length = Convert.ToInt32(Math.Floor(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture)));

            //how many steps to travel through the curve
            //divide by curves.Length to scale this with the number of curves
            double steps = length * 2 / curves.Length;
            //how much to increment t by with every loop
            double increment = 1 / steps;
            //how much along the curve we have traveled so far
            double travelled = 0;
            //where to get the next point on a given curve
            //assign increment to get the next intended point
            double t    = increment;
            Point  prev = new Point();

            prev.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            prev.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));
            //which curve we are looking at
            int curvenumber = 0;

            while (curvenumber < curves.Length)
            {
                Point  next     = curves[curvenumber].Bezier(t);
                double distance = Dewlib.GetDistance(prev.x, prev.y, next.x, next.y);
                travelled += distance;
                prev       = next;
                if (travelled >= length)
                {
                    return(next);
                }

                t += increment;
                if (t > 1)
                {
                    curvenumber++;
                    t -= 1;
                }
            }

            //If we reached the end of the slider without accumulated sliderlength distance,
            //just assume that the last point is the last point of the bezier curve
            return(curves[curves.Length - 1].Bezier(1));
        }
Beispiel #19
0
        protected override int[] GetTickLocations()
        {
            //Necessary to avoid cases where the pixellength is something like 105.000004005432
            int length = Convert.ToInt32(Math.Floor(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture)));

            double slidervelocity = this.GetSliderVelocity();
            double tickrate       = Double.Parse(map.GetTag("Difficulty", "SliderTickRate"), CultureInfo.InvariantCulture);
            int    ticklength     = (int)Math.Round(slidervelocity * (100 / tickrate));

            List <int> ticks = new List <int>();

            if (length <= ticklength)
            {
                return(new int[0]);
            }

            //How far along a single curve we have traveled
            //Initialize to ticklength to make the while loop work for the first curve
            int accumulatedlength = ticklength;
            //How much along the entire slider we have traveled
            //Necessary to keep track of in case there are more curves than the slider length allows
            int totalaccumulatedlength = ticklength;

            //Special case for last curve, hence the curves.Length-1
            for (int i = 0; i < curves.Length; i++)
            {
                //Keep traveling down the curve accumulating ticks until we reach the length of the curve
                while (accumulatedlength < curves[i].DistanceBetween())
                {
                    ticks.Add(curves[i].GetPointAlong(accumulatedlength).IntX());
                    accumulatedlength      += ticklength;
                    totalaccumulatedlength += ticklength;
                    //>= since ticks can't appear on slider ends
                    if (totalaccumulatedlength >= length)
                    {
                        //Don't want to bother with trying to break out of two loops
                        return(ticks.ToArray());
                    }
                }
                accumulatedlength -= (int)Math.Round(curves[i].DistanceBetween());
            }

            return(ticks.ToArray());
        }
Beispiel #20
0
        //Formats a string of control points into an array of points
        //Does NOT include the first hit point
        private Point[] FormatControlPoints()
        {
            //Control point string will look like: B|380:120|332:96|332:96|304:124

            //Gets a list of strings containing each control point by splitting up the control point string
            string[] sliderpoints = HitObjectParser.GetProperty(id, "controlpoints").Split('|');

            List <Point> temppoints = new List <Point>();

            //Parse each point as a Point object
            foreach (string point in sliderpoints)
            {
                string[] pair = point.Split(':');
                temppoints.Add(new Point(Double.Parse(pair[0], CultureInfo.InvariantCulture), Double.Parse(pair[1], CultureInfo.InvariantCulture)));
            }

            //Return this list of points as an array
            return(temppoints.ToArray());
        }
Beispiel #21
0
        //Gets the number of slider ticks, including slider repeats (but not slider ends)
        //Calculated the same regardless of slider type
        protected int GetTickCount()
        {
            double slidervelocity = this.GetSliderVelocity();

            double tickrate = Double.Parse(map.GetTag("Difficulty", "SliderTickRate"), CultureInfo.InvariantCulture);

            double length = Math.Round(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture), 4);

            int sliderruns = Int32.Parse(HitObjectParser.GetProperty(id, "repeat"));

            double ticklength = Math.Round(slidervelocity * (100 / tickrate), 4);

            int tickcount = (int)Math.Floor(length / ticklength);

            if (Math.Abs(length % ticklength) < Double.Epsilon)
            {
                tickcount--;
            }

            return(tickcount * sliderruns);
        }
Beispiel #22
0
        //Gets the number of slider ticks, including slider repeats (but not slider ends)
        //Calculated the same regardless of slider type
        protected int GetTickCount()
        {
            double slidervelocity = this.GetSliderVelocity();

            double tickrate = Double.Parse(map.GetTag("Difficulty", "SliderTickRate"), CultureInfo.InvariantCulture);
            //Necessary to avoid cases where the pixellength is something like 105.000004005432
            int length = Convert.ToInt32(Math.Floor(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture)));

            int sliderruns = Int32.Parse(HitObjectParser.GetProperty(id, "repeat"));

            int ticklength = (int)Math.Round(slidervelocity * (100 / tickrate));

            int tickcount = length / ticklength;

            if (length % ticklength == 0)
            {
                tickcount--;
            }

            return(tickcount * sliderruns);
        }
Beispiel #23
0
        protected override Point GetLastPoint()
        {
            double length = Math.Round(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture), 4);

            //Only one curve
            if (curves.Length == 1)
            {
                return(curves[0].GetPointAlong(length));
            }
            else
            {
                double accumulatedlength = 0;
                //Special behavior is needed for the last curve, hence the curves.Length-1
                for (int i = 0; i < curves.Length - 1; i++)
                {
                    accumulatedlength += curves[i].DistanceBetween();
                }
                double lengthdifference = length - accumulatedlength;
                return(curves[curves.Length - 1].GetPointAlong(lengthdifference));
            }
        }
Beispiel #24
0
        //Calculates the Milliseconds per Beat at a specified time by searching
        //through the entire timing points section
        //Timing points inside sliders don't affect the slider itself
        protected double GetMpB()
        {
            int ms = Int32.Parse(HitObjectParser.GetProperty(id, "time"));

            //Get all the timing sections of the beatmap
            string[] timings = this.map.GetSection("TimingPoints");
            //Just in case there is only one timing point
            string timingpoint = timings[0];

            //Find the section that applies to the given time
            for (int i = 0; i < timings.Length; i++)
            {
                //Split the string by commas to get all the relevant times
                string[] attributes = timings[i].Split(',');
                //Trim each string just in case
                attributes = Dewlib.TrimStringArray(attributes);

                if (Int32.Parse(attributes[0]) > ms)
                {
                    break;
                }

                else if (Double.Parse(attributes[1], CultureInfo.InvariantCulture) > 0)
                {
                    timingpoint = timings[i];
                }
                else
                {
                    continue;
                }
            }

            if (timingpoint == null)
            {
                throw new Exception("Error, no relevant timing point\nms=" + ms);
            }

            string[] properties = timingpoint.Split(',');
            return(Double.Parse(properties[1], CultureInfo.InvariantCulture));
        }
Beispiel #25
0
        protected override Point GetLastPoint()
        {
            //Necessary to avoid cases where the pixellength is something like 105.000004005432
            int length = Convert.ToInt32(Math.Floor(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture)));

            //Only one curve
            if (curves.Length == 1)
            {
                return(curves[0].GetPointAlong(length));
            }
            else
            {
                double accumulatedlength = 0;
                //Special behavior is needed for the last curve, hence the curves.Length-1
                for (int i = 0; i < curves.Length - 1; i++)
                {
                    accumulatedlength += curves[i].DistanceBetween();
                }
                double lengthdifference = length - accumulatedlength;
                return(curves[curves.Length - 1].GetPointAlong(lengthdifference));
            }
        }
Beispiel #26
0
        //Uses the given list of control points to construct a list of bezier curves
        //to account for red points
        public BezierSlider(string id, Beatmap amap) : base(id, amap)
        {
            //Get the initial hit point of the slider
            //Split into three lines for readibility
            Point initialcoord = new Point();

            initialcoord.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            initialcoord.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));

            List <BezierCurve> accumulatedcurves = new List <BezierCurve>();

            List <Point> allcontrolpoints = new List <Point>();

            allcontrolpoints.Add(initialcoord);
            allcontrolpoints.AddRange(controlpoints);
            Point[][] curvepoints = LibFuncs.SplitPointList(allcontrolpoints.ToArray());

            foreach (Point[] curve in curvepoints)
            {
                accumulatedcurves.Add(new BezierCurve(curve));
            }

            curves = accumulatedcurves.ToArray();
        }
Beispiel #27
0
        //Calculated the same regardless of slider type so can already be implemented
        public int[] GetHitTimes()
        {
            List <int> times = new List <int>();

            //When slider starts
            int    starttime = Int32.Parse(HitObjectParser.GetProperty(id, "time"));
            double MpB       = this.GetMpB();
            //How long the slider is in existance (without considering repeats)
            //slidertime = (pixellength / (slidervelocity * 100)) * MillisecondsPerBeat
            //(Order of operations is important kids! Otherwise you end up with slidertimes of 5000000 :o)
            int slidertime = Convert.ToInt32((Double.Parse(HitObjectParser.GetProperty(id, "pixellength"), CultureInfo.InvariantCulture) / (this.GetSliderVelocity() * 100)) * MpB);
            //How long each tick is apart from each other
            //ticktime = MillisecondsPerBeat / tickrate
            int ticktime = Convert.ToInt32(MpB / Double.Parse(map.GetTag("difficulty", "slidertickrate"), CultureInfo.InvariantCulture));
            //How many times the slider runs
            int sliderruns = Int32.Parse(HitObjectParser.GetProperty(id, "repeat"));
            //How many ticks are in the slider (without repeats)
            //This is because later we use tickcount to tell how many times to add a time
            //for a given slider run
            int tickcount = this.GetTickCount() / sliderruns;

            //The time from the last tick to the slider end
            //If there are no ticks, then this just become slidertime
            int sliderenddiff = (slidertime) - (tickcount * ticktime);

            //Keeps track of what time we are at when travelling through the slider
            int currenttime = starttime;

            for (int runnum = 1; runnum <= sliderruns; runnum++)
            {
                if (runnum == 1)
                {
                    //Add the initial slider hit
                    times.Add(currenttime);
                    //Add the tick times
                    for (int ticknum = 0; ticknum < tickcount; ticknum++)
                    {
                        currenttime += ticktime;
                        times.Add(currenttime);
                    }
                    //Add the slider end
                    currenttime += sliderenddiff;
                    times.Add(currenttime);
                }
                else if (runnum % 2 == 0)
                {
                    //Add the first tick after the slider end
                    currenttime += sliderenddiff;
                    times.Add(currenttime);
                    //Don't skip the first tick since we need to include the slider head too
                    for (int ticknum = 0; ticknum < tickcount; ticknum++)
                    {
                        currenttime += ticktime;
                        times.Add(currenttime);
                    }
                }
                else if (runnum % 2 == 1)
                {
                    //Add the tick times
                    for (int ticknum = 0; ticknum < tickcount; ticknum++)
                    {
                        currenttime += ticktime;
                        times.Add(currenttime);
                    }
                    //Add the slider end
                    currenttime += sliderenddiff;
                    times.Add(currenttime);
                }
            }

            return(times.ToArray());
        }
Beispiel #28
0
        protected override Beatmap ParseFile(TextReader stream)
        {
            var beatmap = new Beatmap
            {
                HitObjects    = new List <HitObject>(),
                ControlPoints = new List <ControlPoint>(),
                ComboColors   = new List <Color4>(),
                BeatmapInfo   = new BeatmapInfo
                {
                    Metadata       = new BeatmapMetadata(),
                    BaseDifficulty = new BaseDifficulty(),
                },
            };

            HitObjectParser parser = null;

            var    section = Section.None;
            string line;

            while (true)
            {
                line = stream.ReadLine();
                if (line == null)
                {
                    break;
                }
                if (string.IsNullOrEmpty(line))
                {
                    continue;
                }
                if (line.StartsWith(@"osu file format v"))
                {
                    continue;
                }

                if (line.StartsWith(@"[") && line.EndsWith(@"]"))
                {
                    if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
                    {
                        throw new InvalidDataException($@"Unknown osu section {line}");
                    }
                    continue;
                }

                string val = line, key = null;
                if (section != Section.Events && section != Section.TimingPoints && section != Section.HitObjects)
                {
                    key = val.Remove(val.IndexOf(':')).Trim();
                    val = val.Substring(val.IndexOf(':') + 1).Trim();
                }
                switch (section)
                {
                case Section.General:
                    handleGeneral(beatmap, key, val);
                    parser = Ruleset.GetRuleset(beatmap.BeatmapInfo.Mode).CreateHitObjectParser();
                    break;

                case Section.Editor:
                    handleEditor(beatmap, key, val);
                    break;

                case Section.Metadata:
                    handleMetadata(beatmap, key, val);
                    break;

                case Section.Difficulty:
                    handleDifficulty(beatmap, key, val);
                    break;

                case Section.Events:
                    handleEvents(beatmap, val);
                    break;

                case Section.TimingPoints:
                    handleTimingPoints(beatmap, val);
                    break;

                case Section.Colours:
                    handleColours(beatmap, key, val);
                    break;

                case Section.HitObjects:
                    var obj = parser?.Parse(val);

                    if (obj != null)
                    {
                        obj.SetDefaultsFromBeatmap(beatmap);
                        beatmap.HitObjects.Add(obj);
                    }
                    break;
                }
            }

            return(beatmap);
        }
Beispiel #29
0
        protected override void ParseFile(StreamReader stream, Sheetmusic sheetmusic) // 解碼
        {
            sheetmusic.SheetmusicInfo.SheetmusicVersion = sheetmusicVersion;

            Section section          = Section.None;
            bool    hasCustomColours = false;

            string line;

            while ((line = stream.ReadLine()) != null)
            {
                if (line.Equals(" ") || line.Equals(""))
                {
                    continue;
                }

                if (line.StartsWith("//"))
                {
                    continue;
                }

                if (line.StartsWith(@"straight file format v"))
                {
                    sheetmusic.SheetmusicInfo.SheetmusicVersion = int.Parse(line.Substring(13));
                    continue;
                }

                if (line.StartsWith(@"[") && line.EndsWith(@"]"))
                {
                    section = (Section)Enum.Parse(typeof(Section), line.Substring(1, line.Length - 2));
                    continue;
                }

                switch (section)
                {
                case Section.General:
                    handleGeneral(sheetmusic, line);
                    break;

                case Section.Metadata:
                    handleMetadata(sheetmusic, line);
                    break;

                case Section.Difficulty:
                    handleDifficulty(sheetmusic, line);
                    break;

                //case Section.Events:
                //    handleEvents(sheetmusic, line, ref storyboardSprite, ref timelineGroup);
                //    break;
                case Section.TimingPoints:
                    handleTimingPoints(sheetmusic, line);
                    break;

                //case Section.Colours:
                //    handleColours(sheetmusic, line, ref hasCustomColours);
                //    break;
                case Section.HitObjects:

                    // If the ruleset wasn't specified, assume the osu!standard ruleset.
                    if (parser == null)
                    {
                        parser = new Rulesets.Objects.Parsers.ConvertHitObjectParser();
                    }

                    var obj = parser.Parse(line);

                    if (obj != null)
                    {
                        sheetmusic.HitObjects.Add(obj);
                    }

                    break;
                    //case Section.Variables:
                    //    handleVariables(line);
                    //    break;
                }
            }

            foreach (var hitObject in sheetmusic.HitObjects)
            {
                hitObject.ApplyDefaults(sheetmusic.ControlPointInfo, sheetmusic.SheetmusicInfo.BaseDifficulty);
            }
        }
Beispiel #30
0
        protected override int[] GetTickLocations()
        {
            double length = Math.Round(Double.Parse(HitObjectParser.GetProperty(id, "pixelLength"), CultureInfo.InvariantCulture), 4);

            int sliderruns = Int32.Parse(HitObjectParser.GetProperty(id, "repeat"));
            //Only need ticks for one slider length (no repeats needed)
            //Also no need for double conversion since TickCount is always divisible by sliderruns
            int tickcount = this.GetTickCount() / sliderruns;

            double slidervelocity = this.GetSliderVelocity();
            double tickrate       = Double.Parse(map.GetTag("Difficulty", "SliderTickRate"), CultureInfo.InvariantCulture);
            double ticklength     = Math.Round(slidervelocity * (100 / tickrate), 4);

            if (length <= ticklength)
            {
                return(new int[0]);
            }

            List <Point> ticks = new List <Point>();

            //how many steps to travel through the curve
            //divide by curves.Length to scale this with the number of curves
            double steps = length * 2 / curves.Length;
            //how much to increment t by with every loop
            double increment = 1 / steps;
            //how much along the curve we have traveled so far
            double travelled = 0;
            //where to get the next point on a given curve
            //assign increment to get the next intended point
            double t    = increment;
            Point  prev = new Point();

            prev.x = Int32.Parse(HitObjectParser.GetProperty(id, "x"));
            prev.y = Int32.Parse(HitObjectParser.GetProperty(id, "y"));
            //which curve we are looking at
            int curvenumber = 0;

            while (curvenumber < curves.Length)
            {
                Point  next     = curves[curvenumber].Bezier(t);
                double distance = LibFuncs.GetDistance(prev.x, prev.y, next.x, next.y);
                travelled += distance;
                prev       = next;
                if (travelled >= ticklength)
                {
                    ticks.Add(next);
                    travelled = 0;
                    if (ticks.Count == tickcount)
                    {
                        break;
                    }
                }
                t += increment;
                if (t > 1)
                {
                    curvenumber++;
                    t -= 1;
                }
            }

            if (travelled > 0)
            {
                throw new Exception("Error, too many ticks to get in bezier curve, travelled=" + travelled);
            }

            List <int> locations = new List <int>();

            foreach (Point i in ticks)
            {
                locations.Add(i.IntX());
            }

            return(locations.ToArray());
        }