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