using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace JudgeModule { public class NoteManager { private GameObject offset, noteobj, deactives, appear, disappear, judgetext; private JudgeTextManager judgetextmanager; private Vector3 initialPos; private float BPM; private Func GetLastNote; private int cntWait = 20; private const int cntTotal = 20; private Dictionary> waits = new Dictionary>(), enables = new Dictionary>(), disables = new Dictionary>(); private string[] notenames = new string[] { "SBT", "LBT", "SMO", "LMO" }, linenames = new string[] { "BeatLine", "MeasureLine" }, names = new string[] { "SBT", "LBT", "SMO", "LMO", "BeatLine", "MeasureLine" }; private float recentBeatTiming, recentMeasureTiming; public Note CurrentBT { get { float timing = 0; string type = null; foreach (var x in new string[] { "SBT", "LBT" }) { if (enables[x].Count == 0) continue; if (type == null || timing > enables[x][0].Instance.StartTiming) { type = x; timing = enables[x][0].Instance.StartTiming; } } return type == null ? null : enables[type][0].Instance; } } public Note CurrentSMO { get { return enables["SMO"].Count == 0 ? null : enables["SMO"][0].Instance; } } public Note CurrentLMO { get { return enables["LMO"].Count == 0 ? null : enables["LMO"][0].Instance; } } private float MsPerBeat { get { return 60 * 1000f / BPM; } } private float ScrollSpeed { get { return MsPerBeat / 1000f; } } public bool IsEnd { get; private set; } public NoteManager(Dictionary gameObjects, float bpm, Func getlastnote) { offset = gameObjects["offset"]; noteobj = gameObjects["noteobj"]; deactives = gameObjects["deactives"]; appear = gameObjects["appear"]; disappear = gameObjects["disappear"]; judgetext = gameObjects["judgetext"]; judgetextmanager = judgetext.GetComponent(); initialPos = offset.transform.position; BPM = bpm; GetLastNote = getlastnote; foreach (var name in new string[] { "SBT", "LBT", "SMO", "LMO", "BeatLine", "MeasureLine" }) { waits[name] = appear.transform.Cast() .Where(x => x.gameObject.name == name) .Select(x => x.GetComponent()) .ToList(); enables[name] = new List(); disables[name] = new List(); foreach (var c in waits[name]) { c.enables = enables[name]; c.disables = disables[name]; } } IsEnd = false; } public void Controll(float timing) { offset.transform.position = Vector3.left * timing * ScrollSpeed; RelocateControllers(timing); } private void RelocateControllers(float timing) { DeactiveUndecided(); SwitchStandBy(); AssignNotes(timing); AssignLines(timing); } private void DeactiveUndecided() { foreach (var name in notenames) { var controllers = enables[name].ToArray(); foreach (var c in controllers) if (!c.Instance.Activated && !judgetextmanager.IsRegistered(c.Instance) && initialPos.x - c.StartPosition() > Judge.BAD.TimingRange(c.Instance)) { NoteJudger.SetJudge(Judge.MISS, judgetext); judgetextmanager.Register(c.Instance); c.Deactivate(deactives.transform, !c.Instance.IsLong); } } } private void SwitchStandBy() { foreach (var name in names) { var controllers = disables[name].ToArray(); foreach (var c in controllers) if (c.EndPosition(ScrollSpeed) <= disappear.transform.position.x) { var pos = c.transform.position; pos.x = appear.transform.position.x; c.transform.position = pos; c.transform.SetParent(appear.transform); c.gameObject.SetActive(false); disables[name].Remove(c); waits[name].Add(c); if (name != "BeatLine" && name != "MeasureLine") ++cntWait; } } } private void AssignNotes(float timing) { if (cntWait == 0) return; var notes = new List(); for (int i = 0; i < cntWait; ++i) { Note note = GetLastNote(); if (note == null) break; notes.Add(note); } cntWait -= notes.Count; if (cntWait == cntTotal) { IsEnd = true; return; } foreach (var name in notenames) AssignSpecificNotes(timing, notes, name); } private void AssignSpecificNotes(float timing, List lastnotes, string name) { var notes = GetSpecificNotes(lastnotes, (NoteType)Enum.Parse(typeof(NoteType), name)); var cntActive = notes.Count < waits[name].Count ? notes.Count : waits[name].Count; for (int i = 0; i < cntActive; ++i) AssignNote(notes[i], waits[name][i], timing); enables[name].AddRange(waits[name].GetRange(0, cntActive)); waits[name].RemoveRange(0, cntActive); } private List GetSpecificNotes(IEnumerable lastnotes, NoteType type) { return lastnotes.Where(x => x.Type == type) .ToList(); } private void AssignNote(Note note, Controller controller, float timing) { controller.Instance = note; note.Component = controller; controller.transform.position = initialPos + Vector3.right * ((note.StartTiming - timing) * ScrollSpeed); if (controller.name == "SMO") controller.transform.position += (Vector3.up * 50); if (controller.name == "LMO") controller.transform.position += (Vector3.down * 50); controller.transform.SetParent(noteobj.transform); controller.gameObject.SetActive(true); if (note.IsLong) { note.TotalCount = (int)(note.Length / MsPerBeat); StretchLongNote(controller); } } private void StretchLongNote(Controller controller) { float length = controller.Instance.Length * ScrollSpeed; var hold = controller.transform.GetChild(1).GetComponent(); var end = controller.transform.GetChild(2).GetComponent(); hold.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, length); hold.Translate(Vector3.right * (length / 2)); end .Translate(Vector3.right * length); } private void AssignLines(float timing) { foreach (var name in linenames) { foreach (var x in waits[name]) AssignLine(name, timing, x); disables[name].AddRange(waits[name]); waits[name].Clear(); } } private void AssignLine(string name, float timing, Controller controller) { NoteType type = (NoteType)Enum.Parse(typeof(NoteType), name); float next; if (type == NoteType.BeatLine) { next = recentBeatTiming; recentBeatTiming += (MsPerBeat / 4); } else { next = recentMeasureTiming; recentMeasureTiming += MsPerBeat; } Note note = new Note(type, next); controller.Instance = note; note.Component = controller; controller.transform.position = initialPos + Vector3.right * ((note.StartTiming - timing) * ScrollSpeed); controller.transform.SetParent(deactives.transform); controller.gameObject.SetActive(true); } } }