public BMS Parse(string path) { BMS bms = new BMS(); //default encoding: Shift-JIS? Encoding encoding = Encoding.GetEncoding(932); String line; if (!File.Exists(path)) { return null; } using (FileStream fs = File.OpenRead(path)) { //detect charset Ude.CharsetDetector cdet = new Ude.CharsetDetector(); cdet.Feed(fs); cdet.DataEnd(); /* if(cdet.Charset != null) { Console.WriteLine("Charset: {0}, confidence: {1}", cdet.Charset, cdet.Confidence); encoding = Encoding.GetEncoding(cdet.Charset); } else { Console.WriteLine("Detection Failed"); } */ } using (StreamReader sr = new StreamReader(path, encoding)) { bms.path = Directory.GetParent(path).FullName; while((line = sr.ReadLine()) != null) { ProcessBMSLine(line.Trim(), bms); } } SetSubtitle(bms.info); CalculatePulse(bms); FillRealTime(bms); return bms; }
private void CalculatePulse(BMS bms) { //fill omitted line events for(int i = 1; i <= bms.info.maxMeasure; i++) { if(!measureSetIndex.Contains(i)) { bms.bmsEvents.Add(new LineEvent(i, 1)); } } bms.bmsEvents.Sort(); ulong[] accumYList = new ulong[bms.info.maxMeasure+10]; double[] measureLengthList = Enumerable.Repeat((double)1, bms.info.maxMeasure + 1).ToArray(); for (int i = 0; i < bms.bmsEvents.Count(); i++) { if (bms.bmsEvents[i].eventType == EventType.LineEvent) { measureLengthList[bms.bmsEvents[i].measure] = ((LineEvent)bms.bmsEvents[i]).measureLength; } } //fill accumYList accumYList[0] = 0; for (int i = 1; i <= measureLengthList.Length; i++) { accumYList[i] = accumYList[i - 1] + (ulong)(measureLengthList[i - 1] * bms.info.resolution); } //calcY bmsEvents and resolution foreach (BmsEvent be in bms.bmsEvents) { be.calcY(bms.info.resolution, measureLengthList[be.measure], accumYList[be.measure]); } bms.bmsEvents.Sort(); ProcessLn(bms); }
public void loadBMS() { if (!File.Exists(path)) { string[] args = Environment.GetCommandLineArgs(); if (args.Length != 0) path = args[args.Length - 1]; } //Open without argument while (!File.Exists(path)) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "BMS Files|*.bms;*.bme;*.bml;*.pms"; openFileDialog.Title = "Select a BMS File"; if (openFileDialog.ShowDialog() == DialogResult.OK) { path = openFileDialog.FileName; } } BMSParser.BMSParser bmsParser = new BMSParser.BMSParser(); bms = bmsParser.Parse(path); titleText.GetComponent<Text>().text = bms.info.title; subtitleText.GetComponent<Text>().text = bms.info.subtitle; artistText.GetComponent<Text>().text = bms.info.artist; genreText.GetComponent<Text>().text = bms.info.genre; if (bms.info.subartists.Count != 0) subartistText.GetComponent<Text>().text = bms.info.subartists[0]; else subartistText.SetActive(false); if (File.Exists(bms.path + "\\" + bms.info.eyecatch_image)) { Texture2D bgaTex = Util.LoadImageFromPath(bms.path + "\\" + bms.info.eyecatch_image); eyecatchImage.GetComponent<Image>().sprite = Sprite.Create(bgaTex, new Rect(0, 0, bgaTex.width, bgaTex.height), new Vector2(0, 0)); } }
IEnumerator Start() { bmsLoader = GameObject.Find("BMSLoader").GetComponent<BMSLoader>(); bmsLoader.loadBMS(); bms = bmsLoader.bms; yield return new WaitForSeconds(0.1f); Time.timeScale = 0.0f; //set camera variables worldScreenHeight = Camera.main.orthographicSize * 2; worldScreenWidth = worldScreenHeight / Screen.height * Screen.width; if(bms == null) { Debug.Log("Parsing Failed"); } currBpm = bms.info.init_bpm; //get components bgImage = bga.GetComponent<SpriteRenderer>(); layerImage = bgaLayer.GetComponent<SpriteRenderer>(); gstBga = bgaVideo.GetComponent<GstUnityBridgeTexture>(); gstLayer = bgaLayerVideo.GetComponent<GstUnityBridgeTexture>(); //set variables ulong maxSoundObjectId = 0; ulong maxBgaHeaderId = 0; foreach (BmsEvent be in bms.bmsEvents) { if (be.eventType == BMSParser.EventType.NoteEvent && ((NoteEvent)be).id > maxSoundObjectId) maxSoundObjectId = ((NoteEvent)be).id; } foreach (BGAHeader bh in bms.bga.bga_header) { if (bh.id > maxBgaHeaderId) { maxBgaHeaderId = bh.id; } } bgaSprites = new Sprite[maxBgaHeaderId+10]; layerSprites = new Sprite[maxBgaHeaderId+10]; eventLength = bms.bmsEvents.Count; pulseConstant = bms.info.init_bpm * bms.info.resolution / (60 * 4); lastPulse = bms.bmsEvents[bms.bmsEvents.Count - 1].y; resolution = bms.info.resolution; judge = GameObject.Find("Judge"); judgeImage = GameObject.Find("JudgeImage").GetComponent<UnityEngine.UI.Image>(); titleText = GameObject.Find("TitleText").GetComponent<Text>(); subtitleText = GameObject.Find("SubtitleText").GetComponent<Text>(); artistText = GameObject.Find("ArtistText").GetComponent<Text>(); bpmText = GameObject.Find("BpmText").GetComponent<Text>(); bgaText = GameObject.Find("BgaText").GetComponent<Text>(); layerText = GameObject.Find("LayerText").GetComponent<Text>(); pulseText = GameObject.Find("PulseText").GetComponent<Text>(); genreText = GameObject.Find("GenreText").GetComponent<Text>(); timeText = GameObject.Find("TimeText").GetComponent<Text>(); measureText = GameObject.Find("MeasureText").GetComponent<Text>(); totalText = GameObject.Find("TotalText").GetComponent<Text>(); resolutionText = GameObject.Find("ResolutionText").GetComponent<Text>(); soundText = GameObject.Find("SoundCountText").GetComponent<Text>(); comboText = GameObject.Find("ComboText").GetComponent<Text>(); loadingStatusText = GameObject.Find("LoadingStatusText").GetComponent<Text>(); soundObjects = new GameObject[1296]; //set Text titleText.text = "Title: " + bms.info.title; subtitleText.text = "Subtitle: " + bms.info.subtitle; artistText.text = "Artist: " + bms.info.artist; bpmText.text = "Bpm: " + bms.info.init_bpm; genreText.text = "Genre: " + bms.info.genre; totalText.text = "Total: " + bms.info.total; measureText.text = "Measure: 0/" + bms.info.maxMeasure; resolutionText.text = "Resolution: " + bms.info.resolution; loadingStatusText.text = "Loading BGA..."; yield return null; LoadBga(); loadingStatusText.text = "Loading Sound..."; yield return null; LoadSound(bms.info.soundHeaders); loadingStatusText.text = "Drawing Notes..."; yield return null; NotePlacement(); Component[] sources = FindObjectsOfType(typeof(AudioSource)) as Component[]; audioSources = new AudioSource[sources.Length]; sources.CopyTo(audioSources, 0); //Check how many sounds are playing.. InvokeRepeating("CurrentlyPlaying", 1f, 0.5f); DrawBMSGraph dbg = graphPanel.GetComponent<DrawBMSGraph>(); dbg.DrawGraph(bms.bmsEvents); loadingStatusText.text = "Done"; yield return null; loadingScreen.SetActive(false); isLoaded = true; timeOffset = Time.time; dbg.timeOffset = timeOffset; Time.timeScale = 1.0f; }
private void ProcessLn(BMS bms) { int eventCount = bms.bmsEvents.Count(); for (int i = 0; i < eventCount; i++) { if (bms.bmsEvents[i].eventType == EventType.NoteEvent) { NoteEvent ne = (NoteEvent)bms.bmsEvents[i]; //green note if ((ne.channel >= 181 && ne.channel <= 189) || (ne.channel >= 217 && ne.channel <= 225)) { int j = i + 1; //find end note while (j < eventCount - 1 && (bms.bmsEvents[j].eventType != EventType.NoteEvent || ((NoteEvent)bms.bmsEvents[j]).x != ne.x)) { j++; } if (j < eventCount) { ne.l = bms.bmsEvents[j].y - ne.y; bms.bmsEvents.RemoveAt(j); eventCount--; } } //lnobj else if ((int)ne.id == bms.info.lnObj) { int j = i - 1; while (j >= 0 && (bms.bmsEvents[j].eventType != EventType.NoteEvent || ((NoteEvent)bms.bmsEvents[j]).x != ne.x)) { j--; } if (j != -1) { ((NoteEvent)bms.bmsEvents[j]).l = ne.y - bms.bmsEvents[j].y; bms.bmsEvents.RemoveAt(i); eventCount--; i--; } } } } }
private void ProcessBMSLine(String line, BMS bms) { char[] seperators = { ' ', '\t', ' ' }; String[] args = line.Split(seperators, 2); if ( !(args[0].StartsWith("#")) ) return; args[0] = args[0].ToUpper(); if (args.Count() > 1) { if (args[0].StartsWith("#WAV")) //add soundchannel, note information will be added later. { int id = BMSUtil.HexToInt(args[0].Substring(4, 2)); bms.info.soundHeaders.Add( new SoundHeader(id, args[1]) ); } else if (args[0].StartsWith("#BMP")) { int id = BMSUtil.HexToInt(args[0].Substring(4, 2)); bms.bga.bga_header.Add(new BGAHeader(id, args[1])); } else if (args[0] == "#BPM") //init bpm { bms.info.init_bpm = Convert.ToDouble(args[1]); } else if (args[0].StartsWith("#BPM")) //bpm changing events, add to bpmHeader { int id = BMSUtil.HexToInt(args[0].Substring(4, 2)); bms.info.bpmHeaders[id] = new BpmHeader(id, Convert.ToDouble(args[1])); } else if (args[0].StartsWith("#STOP")) //Stop events { int id = BMSUtil.HexToInt(args[0].Substring(5, 2)); bms.info.stopHeaders[id] = new StopHeader(id, Convert.ToUInt64(args[1])); } else if (args[0] == "#TITLE") { bms.info.title = args[1]; } else if (args[0] == "#SUBTITLE") { bms.info.subtitle = args[1]; } else if (args[0] == "#PLAYER") { int player = Convert.ToInt32(args[1]); if(player == 3) { bms.info.mode_hint = "beat-14k"; } } else if (args[0] == "#GENRE") { bms.info.genre = args[1]; } else if (args[0] == "#ARTIST") { bms.info.artist = args[1]; } else if (args[0] == "#PLAYLEVEL") { if (!ulong.TryParse(args[1], out bms.info.level)) bms.info.level = 0; } else if (args[0] == "#RANK") { int rank = Convert.ToInt32(args[1]); //adjust judge_rank based on LR2's #RANK criteria. if (rank == 0) bms.info.judge_rank *= (8 / 21); else if (rank == 1) bms.info.judge_rank *= (15 / 21); else if (rank == 2) bms.info.judge_rank *= (18 / 21); } else if (args[0] == "#STAGEFILE") { bms.info.eyecatch_image = args[1]; } else if (args[0] == "#TOTAL") { bms.info.total = Convert.ToDouble(args[1]); } else if (args[0] == "#VOLWAV") { //VOLWAV is Obsoleted } else if (args[0] == "#SUBARTIST") { bms.info.subartists.Add(args[1]); } else if (args[0] == "#BANNER") { bms.info.banner_image = args[1]; } else if (args[0] == "#DIFFICULTY") { bms.info.difficulty = Convert.ToInt32(args[1]); } else if (args[0] == "#LNOBJ") { bms.info.lnObj = BMSUtil.HexToInt(args[1]); } else if (args[0] == "#LNTYPE") { //LNTYPE is almost obsolete? } else if (args[0] == "#BACKBMP") { bms.info.back_bmp = args[1]; } else if (args[0] == "#COMMENT") { bms.info.comment = args[1]; } } else { args = line.Split(':'); if (args.Count() < 2 || args[0].Length < 6) return; //TODO if 192 % args.count != 0 change resolution int measure = Convert.ToInt32(args[0].Substring(1, 3)); int channel = BMSUtil.HexToInt(args[0].Substring(4, 2)); if (bms.info.maxMeasure < measure) bms.info.maxMeasure = measure; //measure length channel if(channel == 2) { bms.bmsEvents.Add(new LineEvent(measure, Convert.ToDouble(args[1]))); measureSetIndex.Add(measure); return; } IEnumerable<string> notes = BMSUtil.Split(args[1], 2); IEnumerator<string> noteEnum = notes.GetEnumerator(); int argsLength = notes.Count<string>(); int argIndex = 0; double measureDiv; while(noteEnum.MoveNext()) { if(noteEnum.Current!= "00") { measureDiv = (double)argIndex / argsLength; int id = BMSUtil.HexToInt(noteEnum.Current); if (channel == 3) { //channel 03 use 00-FF hex int bpm = Convert.ToInt32(noteEnum.Current, 16); bms.bmsEvents.Add(new BpmEvent(bpm, measure, measureDiv)); } //bga base else if(channel == 4) { bool isVideo = false; if (bms.bga.bga_header.Find(x => (int)x.id == id) != null) { isVideo = IsVideo(bms.bga.bga_header.Find(x => (int)x.id == id).name); } bms.bmsEvents.Add(new BGAEvent(id, measure, measureDiv, EventType.BGAEvent, isVideo)); } //bga poor else if (channel == 6) { bool isVideo = false; if (bms.bga.bga_header.Find(x => (int)x.id == id) != null) { isVideo = IsVideo(bms.bga.bga_header.Find(x => (int)x.id == id).name); } bms.bmsEvents.Add(new BGAEvent(id, measure, measureDiv, EventType.PoorEvent, isVideo)); } //bga layer else if(channel == 7) { bool isVideo = false; if (bms.bga.bga_header.Find(x => (int)x.id == id) != null) { isVideo = IsVideo(bms.bga.bga_header.Find(x => (int)x.id == id).name); } bms.bmsEvents.Add(new BGAEvent(id, measure, measureDiv, EventType.LayerEvent, isVideo)); } //channel 08 => Find bpm from bpmHeader and add BpmEvent else if (channel == 8) { double bpm = bms.info.bpmHeaders.Find(x => (x != null && x.id == id)).bpm; bms.bmsEvents.Add(new BpmEvent(bpm, measure, measureDiv)); } //stop else if(channel == 9) { ulong stopDuration = bms.info.stopHeaders.Find(x => (x != null && x.id == (ulong)id)).duration; bms.bmsEvents.Add(new StopEvent(stopDuration, measure, measureDiv)); } //note channel else bms.bmsEvents.Add(new NoteEvent(true, id, measure, measureDiv, channel)); } argIndex++; } } }
private void FillRealTime(BMS bms) { double currTime = 0; ulong currPulse = 0; ulong deltaPulse = 0; double currBpm = bms.info.init_bpm; ulong resolution = bms.info.resolution; double pulseConst = 4 * 60 / (currBpm * resolution); BmsEvent currEvent; for (int i = 0; i < bms.bmsEvents.Count; i++) { currEvent = bms.bmsEvents[i]; deltaPulse = currEvent.y - currPulse; currPulse = currEvent.y; currTime += pulseConst * deltaPulse; currEvent.time = currTime; if(currEvent.eventType == EventType.BpmEvent) { currBpm = ((BpmEvent)currEvent).bpm; pulseConst = 4 * 60 / (currBpm * resolution); } else if(currEvent.eventType == EventType.StopEvent) { ((StopEvent)currEvent).durationTime = pulseConst * ((StopEvent)currEvent).duration; } } }