public BaseCircle(BaseCircle baseInstance) { //Copy from baseInstance Location = baseInstance.Location; Radius = baseInstance.Radius; StartTime = baseInstance.StartTime; Type = baseInstance.Type; Effect = baseInstance.Effect; }
private void Parse(string bm) { Info.Filename = bm; Info.BeatmapHash = MD5FromFile(bm); using (StreamReader sR = new StreamReader(bm)) { string currentSection = ""; while (sR.Peek() != -1) { string line = sR.ReadLine(); //Check for blank lines if ((line == "") || (line.Length < 2)) continue; //Check for section tag if (line.Substring(0, 1) == "[") { currentSection = line; continue; } //Check for commented-out line if (line.Substring(0, 2) == "//") continue; //Check for version string if (line.Length > 17) { if (line.Substring(0, 17) == "osu file format v") { Info.Format = Convert.ToInt32(line.Substring(17).Replace(Environment.NewLine, "").Replace(" ", "")); } } //Do work for [General], [Metadata], [Difficulty] and [Editor] sections if ((currentSection == "[General]") || (currentSection == "[Metadata]") || (currentSection == "[Difficulty]") || (currentSection == "[Editor]")) { string[] reSplit = line.Split(':'); string cProperty = reSplit[0]; //Check for blank value string cValue = line.Length == reSplit[0].Length ? "" : reSplit[1].Trim(); //Import properties into Info switch (cProperty) { case "EditorBookmarks": { string[] marks = cValue.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); foreach (string m in marks.Where(m => m != "")) { Info.EditorBookmarks.Add(Convert.ToInt32(m)); } } break; case "Bookmarks": { string[] marks = cValue.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); foreach (string m in marks.Where(m => m != "")) { Info.Bookmarks.Add(Convert.ToInt32(m)); } } break; case "Tags": string[] tags = cValue.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); foreach (string t in tags) Info.Tags.Add(t); break; case "Mode": Info.Mode = (GameMode)Convert.ToInt32(cValue); break; case "OverlayPosition": Info.OverlayPosition = (OverlayOptions)Convert.ToInt32(cValue); break; case "AlwaysShowPlayfield": Info.AlwaysShowPlayfield = Convert.ToBoolean(Convert.ToInt32(cValue)); break; default: FieldInfo fi = Info.GetType().GetField(cProperty); PropertyInfo pi = Info.GetType().GetProperty(cProperty); if (fi != null) { if ((fi.FieldType == typeof(double?)) || (fi.FieldType == typeof(double))) fi.SetValue(Info, Convert.ToDouble(cValue)); else if ((fi.FieldType == typeof(int?)) || (fi.FieldType == typeof(int))) fi.SetValue(Info, Convert.ToInt32(cValue)); else if (fi.FieldType == typeof(string)) fi.SetValue(Info, cValue); break; } if ((pi.PropertyType == typeof(double?)) || (pi.PropertyType == typeof(double))) pi.SetValue(Info, Convert.ToDouble(cValue), null); else if ((pi.PropertyType == typeof(int?)) || (pi.PropertyType == typeof(int))) pi.SetValue(Info, Convert.ToInt32(cValue), null); else if (pi.PropertyType == typeof(string)) pi.SetValue(Info, cValue, null); break; } continue; } //The following are version-dependent, the version is stored as a numeric value inside Info.Format //Do work for [Events] section if (currentSection == "[Events]") { switch (Info.Format) { case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: string[] reSplit = line.Split(','); if (reSplit[0] == "0") { BackgroundInfo tempEvent = new BackgroundInfo(); tempEvent.StartTime = Convert.ToInt32(reSplit[1]); tempEvent.Filename = reSplit[2].Replace("\"", ""); Info.Events.Add(tempEvent); } else if ((reSplit[0] == "1") || (reSplit[0].ToLower() == "video")) { VideoInfo tempEvent = new VideoInfo(); tempEvent.StartTime = Convert.ToInt32(reSplit[1]); tempEvent.Filename = reSplit[2]; Info.Events.Add(tempEvent); } else if (reSplit[0] == "2") { BreakInfo tempEvent = new BreakInfo(); tempEvent.StartTime = Convert.ToInt32(reSplit[1]); tempEvent.EndTime = Convert.ToInt32(reSplit[2]); Info.Events.Add(tempEvent); } else if (reSplit[0] == "3") { ColourInfo tempEvent = new ColourInfo(); tempEvent.StartTime = Convert.ToInt32(reSplit[1]); tempEvent.R = Convert.ToInt32(reSplit[2]); tempEvent.G = Convert.ToInt32(reSplit[3]); tempEvent.B = Convert.ToInt32(reSplit[4]); Info.Events.Add(tempEvent); } break; } } //Do work for [TimingPoints] section if (currentSection == "[TimingPoints]") { TimingPointInfo tempTimingPoint = new TimingPointInfo(); double[] values = { 0, 0, 4, 0, 0, 100, 0, 0, 0 }; string[] reSplit = line.Split(','); for (int i = 0; i < reSplit.Length; i++) { values[i] += Convert.ToDouble(reSplit[i]); } tempTimingPoint.Time = Convert.ToDouble(values[0]); tempTimingPoint.BpmDelay = Convert.ToDouble(values[1]); tempTimingPoint.TimeSignature = Convert.ToInt32(values[2]); tempTimingPoint.SampleSet = Convert.ToInt32(values[3]); tempTimingPoint.CustomSampleSet = Convert.ToInt32(values[4]); tempTimingPoint.VolumePercentage = Convert.ToInt32(values[5]); tempTimingPoint.InheritsBPM = !Convert.ToBoolean(Convert.ToInt32(values[6])); tempTimingPoint.VisualOptions = (TimingPointOptions)Convert.ToInt32(values[7]); Info.TimingPoints.Add(tempTimingPoint); } //Do work for [Colours] section if (currentSection == "[Colours]") { switch (Info.Format) { case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: if (line.Substring(0, line.IndexOf(':', 1)).Trim() == "SliderBorder") { string value = line.Substring(line.IndexOf(':', 1) + 1).Trim(); string[] reSplit = value.Split(','); Info.SliderBorder = new ColourInfo(); Info.SliderBorder.R = Convert.ToInt32(reSplit[0]); Info.SliderBorder.G = Convert.ToInt32(reSplit[1]); Info.SliderBorder.B = Convert.ToInt32(reSplit[2]); } else if (line.Substring(0, 5) == "Combo") { string value = line.Substring(line.IndexOf(':', 1) + 1).Trim(); string[] reSplit = value.Split(','); ComboInfo tempCombo = new ComboInfo(); tempCombo.ComboNumber = Convert.ToInt32(line.Substring(5, 1)); tempCombo.Colour.R = Convert.ToInt32(reSplit[0]); tempCombo.Colour.G = Convert.ToInt32(reSplit[1]); tempCombo.Colour.B = Convert.ToInt32(reSplit[2]); Info.ComboColours.Add(tempCombo); } break; } } //Do work for [HitObjects] section if (currentSection == "[HitObjects]") { string[] reSplit = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); BaseCircle newObject = new BaseCircle { Radius = 40 - 4 * (Info.CircleSize - 2), Location = new PointInfo(Convert.ToInt32(reSplit[0]), Convert.ToInt32(reSplit[1])), StartTime = Convert.ToInt32(reSplit[2]), Type = (HitObjectType)Convert.ToInt32(reSplit[3]), Effect = (EffectType)Convert.ToInt32(reSplit[4]) }; if ((newObject.Type & HitObjectType.Slider) > 0) { newObject = new SliderInfo(newObject); ((SliderInfo)newObject).Velocity = Info.SliderMultiplier; switch (reSplit[5].Substring(0, 1)) { case "B": ((SliderInfo)newObject).Type = SliderType.Bezier; break; case "C": ((SliderInfo)newObject).Type = SliderType.CSpline; break; case "L": ((SliderInfo)newObject).Type = SliderType.Linear; break; case "P": ((SliderInfo)newObject).Type = SliderType.PSpline; break; } string[] pts = reSplit[5].Split(new[] { "|" }, StringSplitOptions.None); //Always add the location as a point ((SliderInfo)newObject).Points.Add(newObject.Location); //Always exclude index 1, this will contain the type for (int i = 1; i <= pts.Length - 1; i++) { PointInfo p = new PointInfo(Convert.ToDouble(pts[i].Substring(0, pts[i].IndexOf(":", StringComparison.InvariantCulture))), Convert.ToDouble(pts[i].Substring(pts[i].IndexOf(":", StringComparison.InvariantCulture) + 1))); ((SliderInfo)newObject).Points.Add(p); } ((SliderInfo)newObject).RepeatCount = Convert.ToInt32(reSplit[6]); double tempDbl; if (double.TryParse(reSplit[7], out tempDbl)) { ((SliderInfo)newObject).MaxPoints = tempDbl; } } if ((newObject.Type & HitObjectType.Spinner) > 0) { newObject = new SpinnerInfo(newObject); ((SpinnerInfo)newObject).EndTime = Convert.ToInt32(reSplit[5]); } Info.HitObjects.Add(newObject); } } } foreach (FieldInfo fi in Info.GetType().GetFields()) { FieldInfo ff = GetType().GetField(fi.Name); ff.SetValue(this, fi.GetValue(Info)); } foreach (PropertyInfo pi in Info.GetType().GetProperties()) { PropertyInfo ff = GetType().GetProperty(pi.Name); ff.SetValue(this, pi.GetValue(Info, null), null); } }