using System; using System.Collections.Generic; /// /// 谱面运行数据类,负责将谱面数据解析之后生成运行时数据项,与控制层通讯,这些数据项是查询现有数据项的唯一依据 /// 集合在比较 /// public class ChartRuntimeModel { /// /// 负责管理在项目运行时所产生的物件数据,可以生成Chart对象 /// public SortedSet ChartRuntimeSet = new SortedSet(new UniversalBaseNoteComparer()); /// /// 输入搜索的开始与结束时间,返回符合条件的对象视图 /// public SortedSet SearchRange(float startTime, float endTime) { var view = ChartRuntimeSet.GetViewBetween(new TempBaseNoteComparer(startTime), new TempBaseNoteComparer(endTime)); return view; } /// /// 删除指定的数据项 /// public void DeleteDataItem(RuntimeBaseNoteData obj) { ChartRuntimeSet.Remove(obj); } /// /// 获得指定的数据项引用,如果不存在对应的数据项则会返回null /// public RuntimeBaseNoteData GetDataItem(RuntimeBaseNoteData obj) { if (ChartRuntimeSet.TryGetValue(obj, out var Value)) { return Value; } else { return null; } } /// /// 添加新的数据项 /// public void AddDataItem(RuntimeBaseNoteData obj) { ChartRuntimeSet.Add(obj); } /// /// 遍历所有的数据项,将其转换为持久化谱面数据对象 /// public void GetChartData(Chart chart) { foreach (var item in ChartRuntimeSet) { switch (item) { case RuntimeNoteData: { chart.noteList.Add(new NoteListItem( item.xPos, item.yPos, item.targetTime, item.bpmGroup.GroupNum)); break; } case RuntimeDragData: { chart.dragList.Add(new DragListItem( item.xPos, item.yPos, item.targetTime, item.bpmGroup.GroupNum)); break; } case RuntimeFlickData: { var flick = item as RuntimeFlickData; chart.flickList.Add(new FlickListItem( item.xPos, item.yPos, item.targetTime, item.bpmGroup.GroupNum, flick.direction )); break; } case RuntimeSnakeData: { var snake = item as RuntimeSnakeData; chart.dataFlowList.Add(new DataFlowListItem( snake.xPos, snake.yPos, snake.endXPos, snake.endYPos, snake.targetTime, snake.endTime, true, snake.bpmGroup.GroupNum, snake.referencePoint )); break; } } } } } public class UniversalBaseNoteComparer : IComparer { public int Compare(RuntimeBaseNoteData x, RuntimeBaseNoteData y) { if (x == null && y == null) return 0; if (x == null) return -1; if (y == null) return 1; int timeComparison = x.targetTime.CompareTo(y.targetTime); if (timeComparison != 0) return timeComparison; int xComparison = x.xPos.CompareTo(y.xPos); if (xComparison != 0) return xComparison; int yComparison = x.yPos.CompareTo(y.yPos); if (yComparison != 0) return yComparison; // 如果是蛇节点,比较特有参数 if (x is RuntimeSnakeData xSnake && y is RuntimeSnakeData ySnake) { // 比较蛇节点的特有参数 int endXComparison = xSnake.endXPos.CompareTo(ySnake.endXPos); if (endXComparison != 0) return endXComparison; int endYComparison = xSnake.endYPos.CompareTo(ySnake.endYPos); if (endYComparison != 0) return endYComparison; int endTimeComparison = xSnake.endTime.CompareTo(ySnake.endTime); if (endTimeComparison != 0) return endTimeComparison; int referencePointComparison = xSnake.referencePoint.CompareTo(ySnake.referencePoint); if (referencePointComparison != 0) return referencePointComparison; } // 只比较类型 Type xType = x.GetType(); Type yType = y.GetType(); // 如果类型相同,返回 0(表示相等,SortedSet 不会添加重复项) // 如果类型不同,按类型名称排序 return string.Compare(xType.FullName, yType.FullName, StringComparison.Ordinal); } } /// /// 用于在运行时传递数据的基类 /// public class RuntimeBaseNoteData { public float targetTime { get; set; } public float xPos { get; set; } public float yPos { get; set; } public BPMGroup bpmGroup { get; set; } } public class TempBaseNoteComparer : RuntimeBaseNoteData { public TempBaseNoteComparer(float time) { targetTime = time; } } public class RuntimeNoteData : RuntimeBaseNoteData { public RuntimeNoteData(float targetTime, float xPos, float yPos, BPMGroup bpmGroup) { this.targetTime = targetTime; this.xPos = xPos; this.yPos = yPos; this.bpmGroup = bpmGroup; } } public class RuntimeDragData : RuntimeBaseNoteData { public RuntimeDragData(float targetTime, float xPos, float yPos, BPMGroup bpmGroup) { this.targetTime = targetTime; this.xPos = xPos; this.yPos = yPos; this.bpmGroup = bpmGroup; } } public class RuntimeFlickData : RuntimeBaseNoteData { public FlickDirection direction { get; set; } public RuntimeFlickData(float targetTime, float xPos, float yPos, FlickDirection direction, BPMGroup bpmGroup) { this.targetTime = targetTime; this.xPos = xPos; this.yPos = yPos; this.direction = direction; this.bpmGroup = bpmGroup; } } public class RuntimeSnakeData : RuntimeBaseNoteData { public float endXPos { get; set; } public float endYPos { get; set; } public float endTime { get; set; } public ReferencePointLocation referencePoint { get; set; } public RuntimeSnakeData(float targetTime, float xPos, float yPos, float endXPos, float endYPos, float endTime, ReferencePointLocation referencePoint, BPMGroup bpmGroup) { this.targetTime = targetTime; this.xPos = xPos; this.yPos = yPos; this.endXPos = endXPos; this.endYPos = endYPos; this.endTime = endTime; this.referencePoint = referencePoint; this.bpmGroup = bpmGroup; } }