public void Export(IScoreBookExportPluginArgs args) { var book = args.GetScoreBook(); SusArgs susArgs = JsonConvert.DeserializeObject <SusArgs>(args.GetCustomData() ?? "") ?? new SusArgs(); if (!args.IsQuick) { var vm = new SusExportWindowViewModel(book, susArgs); var window = new SusExportWindow() { DataContext = vm }; var result = window.ShowDialog(); if (!result.HasValue || !result.Value) { throw new UserCancelledException(); } args.SetCustomData(JsonConvert.SerializeObject(susArgs)); } var exporter = new SusExporter(book, susArgs); exporter.Export(args.Stream); }
public void Export(IScoreBookExportPluginArgs args) { var book = args.GetScoreBook(); var buffer = new List <Tuple <int, string> >(); var bars = new BarIndexCalculator(book.Score.TicksPerBeat, book.Score.Events.TimeSignatureChangeEvents); var bpms = book.Score.Events.BPMChangeEvents.OrderBy(p => p.Tick).ToList(); if (bpms[0].Tick == 0) { buffer.Add(Tuple.Create(0, $"*0/0/4,bpm,{bpms[0].BPM}")); } foreach (var bpm in bpms.Skip(1)) { buffer.Add(Tuple.Create(bpm.Tick, $"{GetTime(bpm.Tick)},bpm,{bpm.BPM}")); } var sigs = book.Score.Events.TimeSignatureChangeEvents.OrderBy(p => p.Tick).ToList(); if (sigs[0].Tick == 0) { buffer.Add(Tuple.Create(0, $"*0/0/4,beat,{sigs[0].Numerator}/{sigs[0].Denominator}")); } foreach (var sig in sigs.Skip(1)) { buffer.Add(Tuple.Create(sig.Tick, $"{GetTime(sig.Tick)},beat,{sig.Numerator}/{sig.Denominator}")); } var highSpeeds = book.Score.Events.HighSpeedChangeEvents.OrderBy(p => p.Tick).ToList(); foreach (var highSpeed in highSpeeds) { buffer.Add(Tuple.Create(highSpeed.Tick, $"{GetTime(highSpeed.Tick)},hispeed,{highSpeed.SpeedRatio}")); } // フィールド var sides = new[] { book.Score.Field.Left, book.Score.Field.Right }; var stepTicks = sides.SelectMany(p => p.FieldWall.Points.Select(q => q.Tick)); int li = 0; int ri = 0; var leftSteps = book.Score.Field.Left.FieldWall.Points.OrderBy(p => p.Tick).ToList(); var rightSteps = book.Score.Field.Right.FieldWall.Points.OrderBy(p => p.Tick).ToList(); foreach (var tick in stepTicks.Distinct().OrderBy(p => p)) { if (li < leftSteps.Count - 1) { if (tick >= leftSteps[li + 1].Tick) { li++; } } if (ri < rightSteps.Count - 1) { if (tick >= rightSteps[ri + 1].Tick) { ri++; } } int left = li < leftSteps.Count - 1 ? GetInterpolated(leftSteps[li], leftSteps[li + 1], tick) : GetOffset(leftSteps[li].LaneOffset); int right = ri < rightSteps.Count - 1 ? GetInterpolated(rightSteps[ri], rightSteps[ri + 1], tick) : GetOffset(rightSteps[ri].LaneOffset); buffer.Add(Tuple.Create(tick, $"{GetTime(tick)},fieldset,{left},{right},,")); } WriteField(book.Score.Field.Left, "L"); WriteField(book.Score.Field.Right, "R"); var surfaceLanes = book.Score.SurfaceLanes.Select(p => new { MinTick = p.Points.Min(q => q.Tick), MaxTick = p.Points.Max(q => q.Tick), Value = p }).OrderBy(p => p.MinTick).ToList(); var allocator = new IdentifierAllocator(Enumerable.Range(0, 30).Select(p => p.ToString())); foreach (var lane in surfaceLanes) { var laneNumber = allocator.Allocate(lane.MinTick, lane.MaxTick - lane.MinTick); var points = lane.Value.Points.OrderBy(p => p.Tick).ToList(); int color = lane.Value.LaneColor == SurfaceLaneColor.Red ? 0 : lane.Value.LaneColor == SurfaceLaneColor.Green ? 1 : 2; buffer.Add(Tuple.Create(points[0].Tick, $"{GetTime(points[0].Tick)},laneset,{laneNumber},{color},{GetOffset(points[0].LaneOffset)}")); foreach (var point in points.Skip(1).Take(points.Count - 2)) { buffer.Add(Tuple.Create(point.Tick, $"{GetTime(point.Tick)},lanepos,{laneNumber},{GetOffset(point.LaneOffset)},")); } foreach (var note in lane.Value.Notes.OrderBy(p => p.TickRange.StartTick)) { if (note.TickRange.Duration == 0) { // TAP buffer.Add(Tuple.Create(note.TickRange.StartTick, $"{GetTime(note.TickRange.StartTick)},{(note.IsCritical ? "extap" : "tap")},{laneNumber}")); } else { // HOLD buffer.Add(Tuple.Create(note.TickRange.StartTick, $"{GetTime(note.TickRange.StartTick)},{(note.IsCritical ? "exholdset" : "holdset")},{laneNumber}")); buffer.Add(Tuple.Create(note.TickRange.EndTick, $"{GetTime(note.TickRange.EndTick)},holdend,{laneNumber}")); } } buffer.Add(Tuple.Create(points[points.Count - 1].Tick, $"{GetTime(points[points.Count - 1].Tick)},laneend,{laneNumber},{GetOffset(points[points.Count - 1].LaneOffset)},")); } foreach (var flick in book.Score.Flicks) { string direction = flick.Direction == HorizontalDirection.Left ? "left" : "right"; buffer.Add(Tuple.Create(flick.Position.Tick, $"{GetTime(flick.Position.Tick)},{(flick.IsCritical ? "exflick" : "flick")},{direction},{GetOffset(flick.Position.LaneOffset)}")); } foreach (var bell in book.Score.Bells) { buffer.Add(Tuple.Create(bell.Position.Tick, $"{GetTime(bell.Position.Tick)},heal,{GetOffset(bell.Position.LaneOffset)}")); } foreach (var bullet in book.Score.Bullets) { buffer.Add(Tuple.Create(bullet.Position.Tick, $"{GetTime(bullet.Position.Tick)},shot,{GetOffset(bullet.Position.LaneOffset)},1,1")); } using (var writer = new StreamWriter(args.OutputPath, false, Encoding.GetEncoding("shift-jis"))) { writer.WriteLine($"#title {book.Title}"); writer.WriteLine($"#artist {book.ArtistName}"); writer.WriteLine($"#notes {book.NotesDesignerName}"); writer.WriteLine("#datend"); foreach (var line in buffer.OrderBy(p => p.Item1)) { writer.WriteLine(line.Item2); } writer.WriteLine("+0/4,fin"); } void WriteField(FieldSide fs, string side) { foreach (var guarded in fs.FieldWall.GuardedSections) { buffer.Add(Tuple.Create(guarded.StartTick, $"{GetTime(guarded.StartTick)},setwall,{side}")); buffer.Add(Tuple.Create(guarded.EndTick, $"{GetTime(guarded.EndTick)},delwall,{side}")); } foreach (var guide in fs.SideLanes.Select(p => p.ValidRange)) { buffer.Add(Tuple.Create(guide.StartTick, $"{GetTime(guide.StartTick)},setnoti,{side}")); buffer.Add(Tuple.Create(guide.EndTick, $"{GetTime(guide.EndTick)},delnoti,{side}")); } foreach (var note in fs.SideLanes.SelectMany(p => p.Notes)) { if (note.TickRange.Duration == 0) { buffer.Add(Tuple.Create(note.TickRange.StartTick, $"{GetTime(note.TickRange.StartTick)},{(note.IsCritical ? "extap" : "tap")},{side}")); } else { buffer.Add(Tuple.Create(note.TickRange.StartTick, $"{GetTime(note.TickRange.StartTick)},{(note.IsCritical ? "exholdset" : "holdset")},{side}")); buffer.Add(Tuple.Create(note.TickRange.EndTick, $"{GetTime(note.TickRange.EndTick)},holdend,{side}")); } } } int GetOffset(int offset) { return(480 * offset / book.Score.HalfHorizontalResolution); } int GetInterpolated(FieldPoint first, FieldPoint second, int posTick) { float rate = (float)(posTick - first.Tick) / (second.Tick - first.Tick); return((int)(GetOffset(first.LaneOffset) + GetOffset(second.LaneOffset - first.LaneOffset) * rate)); } string GetTime(int tick) { var pos = bars.GetBarPositionFromTick(tick); int gcd = GetGcd(bars.BarTick, pos.TickOffset); return($"*{pos.BarIndex + 1}/{pos.TickOffset / gcd}/{bars.BarTick / gcd}"); } }