/// <summary> /// Compiles a <see cref="SourceScore"/> to a <see cref="RuntimeScore"/> with default note creation dispatcher. The compiled score will be used by the player. /// </summary> /// <param name="score">The <see cref="SourceScore"/> to compile.</param> /// <param name="compileOptions">Compile options.</param> /// <returns>Compiled score.</returns> public static RuntimeScore CompileScore([NotNull] SourceScore score, [NotNull] ScoreCompileOptions compileOptions) { return(CompileScore(score, compileOptions, CreateNotes)); }
/// <summary> /// Compiles a <see cref="SourceScore"/> to a <see cref="RuntimeScore"/> with custom note creation dispatcher. The compiled score will be used by the player. /// </summary> /// <param name="score">The <see cref="SourceScore"/> to compile.</param> /// <param name="compileOptions">Compile options.</param> /// <param name="notesCreation">The note creation delegate used to dispatch note creation calls.</param> /// <returns>Compiled score.</returns> public static RuntimeScore CompileScore([NotNull] SourceScore score, [NotNull] ScoreCompileOptions compileOptions, [NotNull] NotesCreation notesCreation) { if (score == null) { throw new ArgumentNullException(nameof(score)); } if (compileOptions == null) { throw new ArgumentNullException(nameof(compileOptions)); } // ReSharper cannot infer from "(score.Notes?.Count ?? 0) == 0" that score.Notes is later no longer null. if (score.Notes.Length == 0) { var notes = new RuntimeNote[0]; return(new RuntimeScore(notes)); } var gameNotes = score.Notes; var list = new List <RuntimeNote>(); var conductors = score.Conductors; var currentID = 0; foreach (var note in gameNotes) { var notesToBeAdded = notesCreation(note, conductors, gameNotes, ref currentID); list.AddRange(notesToBeAdded); } var totalNotesCount = list.Count; list.Sort(RuntimeNoteComparisons.ByTimeThenX); // Fix sync relations. Notice that you should keep NextSync's accessing order being after PrevSync. for (var i = 0; i < totalNotesCount - 1; ++i) { var note = list[i]; var nextNote = list[i + 1]; // About this strange behavior, see remarks on RuntimeNote.Ticks. if (note.HitTime.Equals(nextNote.HitTime)) { note.NextSync = nextNote; nextNote.PrevSync = note; } } // TODO: Fix flick/slide group. // Fix offsets var scoreOffset = compileOptions.Offset; foreach (var note in list) { note.HitTime += scoreOffset; } // Generate ScorePrepare note. var scorePrepareNote = new RuntimeNote(); scorePrepareNote.Type = NoteType.ScorePrepare; // This value should correspond to TapPoints' "score-prepare fade-in" animation duration. scorePrepareNote.HitTime = list[0].HitTime - 1.5f; scorePrepareNote.ID = ++currentID; list.Insert(0, scorePrepareNote); var runtimeNotes = list.ToArray(); return(new RuntimeScore(runtimeNotes) { TrackCount = score.TrackCount }); }
public RuntimeScore ReadCompiledScore(Stream stream, string fileName, ReadSourceOptions sourceOptions, ScoreCompileOptions compileOptions) { var sourceScore = ReadSourceScore(stream, fileName, sourceOptions); RuntimeScore runtimeScore; using (var compiler = new SimpleScoreCompiler()) { runtimeScore = compiler.Compile(sourceScore, compileOptions); } return(runtimeScore); }
public RuntimeScore Compile(SourceScore score, ScoreCompileOptions compileOptions) { compileOptions.Offset = (float)score.MusicOffset; return(ScoreCompileHelper.CompileScore(score, compileOptions)); }
public RuntimeScore ReadCompiledScore(Stream stream, string fileName, ReadSourceOptions sourceOptions, ScoreCompileOptions compileOptions) { var score = ReadSourceScore(stream, fileName, sourceOptions); using (var compiler = new SldprojCompiler()) { return(compiler.Compile(score, compileOptions)); } }
/** * A demonstration of the usage of ScoreCompilerHelper methods. */ private RuntimeScore MyCompile(SourceScore score, ScoreCompileOptions compileOptions) { return(ScoreCompileHelper.CompileScore(score, compileOptions, CreateNotes)); }
/// <summary> /// Compiles a <see cref="SourceScore"/> to a <see cref="RuntimeScore"/>, which will be used by the player. /// A <see cref="ScoreCompileOptions"/> object can be specified. /// </summary> /// <param name="score">The <see cref="SourceScore"/> to compile.</param> /// <param name="compileOptions">Compile options.</param> /// <returns>Compiled score.</returns> public RuntimeScore Compile(SourceScore score, ScoreCompileOptions compileOptions) { return(ScoreCompileHelper.CompileScore(score, compileOptions)); }
public void LoadScoreFile([NotNull] string scoreFilePath, int scoreIndex, float scoreOffset) { var theaterDays = Game.ToBaseGame(); var debug = theaterDays.FindSingleElement <DebugOverlay>(); if (string.IsNullOrEmpty(scoreFilePath)) { if (debug != null) { debug.AddLine("ERROR: Score file is not specified."); } return; } if (!File.Exists(scoreFilePath)) { if (debug != null) { debug.AddLine($"ERROR: Score file <{scoreFilePath}> is missing."); } return; } var scoreFormats = theaterDays.PluginManager.GetPluginsOfType <IScoreFormat>(); if (scoreFormats.Count == 0) { if (debug != null) { debug.AddLine("ERROR: No available score reader."); } return; } var sourceOptions = new ReadSourceOptions { ScoreIndex = scoreIndex }; var compileOptions = new ScoreCompileOptions { GlobalSpeed = 1, Offset = scoreOffset }; var successful = false; RuntimeScore runtimeScore = null; SourceScore sourceScore = null; foreach (var format in scoreFormats) { if (!format.SupportsReadingFileType(scoreFilePath)) { continue; } using (var reader = format.CreateReader()) { Stream fileStream = null; if (reader.IsStreamingSupported) { fileStream = File.Open(scoreFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); } if (!successful) { if (format.CanReadAsSource) { try { sourceScore = reader.ReadSourceScore(fileStream, scoreFilePath, sourceOptions); if (!format.CanBeCompiled) { throw new InvalidOperationException("This format must support compiling source score to runtime score."); } using (var compiler = format.CreateCompiler()) { runtimeScore = compiler.Compile(sourceScore, compileOptions); } successful = true; } catch (Exception ex) { if (debug != null) { debug.AddLine($"An exception is thrown while trying to read the score using <{format.PluginDescription}>: {ex.Message}"); debug.AddLine(ex.StackTrace); } } } } if (!successful) { if (format.CanReadAsCompiled) { try { runtimeScore = reader.ReadCompiledScore(fileStream, scoreFilePath, sourceOptions, compileOptions); successful = true; } catch (Exception ex) { if (debug != null) { debug.AddLine($"An exception is thrown while trying to read the score using <{format.PluginDescription}>: {ex.Message}"); debug.AddLine(ex.StackTrace); } } } } if (successful) { break; } fileStream?.Dispose(); } } if (!successful) { if (debug != null) { debug.AddLine($"ERROR: No score reader can read score file <{scoreFilePath}>."); } } else { _sourceScore = sourceScore; RuntimeScore = runtimeScore; if (debug != null) { debug.AddLine($"Loaded score file: {scoreFilePath}"); } } var noteReactor = theaterDays.FindSingleElement <NoteReactor>(); noteReactor?.RecalculateReactions(); var tapPoints = theaterDays.FindSingleElement <TapPoints>(); tapPoints?.RecalcLayout(); }
protected override void OnInitialize() { base.OnInitialize(); var settings = Program.Settings; var scoreFileName = settings.Game.ScoreFile; var debug = Game.AsTheaterDays().FindSingleElement <DebugOverlay>(); if (string.IsNullOrEmpty(scoreFileName)) { if (debug != null) { debug.AddLine("ERROR: Score file is not specified."); } return; } if (!File.Exists(scoreFileName)) { if (debug != null) { debug.AddLine($"ERROR: Score file <{scoreFileName}> is missing."); } return; } if (Program.PluginManager.ScoreFormats.Count == 0) { if (debug != null) { debug.AddLine("ERROR: No available score reader."); } return; } var sourceOptions = new ReadSourceOptions { ScoreIndex = settings.Game.ScoreIndex }; var compileOptions = new ScoreCompileOptions { GlobalSpeed = 1, Offset = settings.Game.ScoreOffset }; var successful = false; RuntimeScore runtimeScore = null; SourceScore sourceScore = null; foreach (var format in Program.PluginManager.ScoreFormats) { if (!format.SupportsReadingFileType(scoreFileName)) { continue; } using (var reader = format.CreateReader()) { using (var fileStream = File.Open(scoreFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (!successful) { if (format.CanReadAsSource) { try { sourceScore = reader.ReadSourceScore(fileStream, scoreFileName, sourceOptions); if (!format.CanBeCompiled) { throw new InvalidOperationException("This format must support compiling source score to runtime score."); } using (var compiler = format.CreateCompiler()) { runtimeScore = compiler.Compile(sourceScore, compileOptions); } successful = true; } catch (Exception ex) { if (debug != null) { debug.AddLine($"An exception is thrown while trying to read the score using <{format.PluginDescription}>: {ex.Message}"); debug.AddLine(ex.StackTrace); } } } } if (!successful) { if (format.CanReadAsCompiled) { try { runtimeScore = reader.ReadCompiledScore(fileStream, scoreFileName, sourceOptions, compileOptions); successful = true; } catch (Exception ex) { if (debug != null) { debug.AddLine($"An exception is thrown while trying to read the score using <{format.PluginDescription}>: {ex.Message}"); debug.AddLine(ex.StackTrace); } } } } if (successful) { break; } } } } if (!successful) { if (debug != null) { debug.AddLine($"ERROR: No score reader can read score file <{scoreFileName}>."); } } else { _score = sourceScore; RuntimeScore = runtimeScore; if (debug != null) { debug.AddLine($"Loaded score file: {scoreFileName}"); } } }