private static void WriteConductor([NotNull] this TextWriter writer, [NotNull] SourceScore sourceScore, int index)
        {
            writer.WriteLine($"		[{index}]");

            var conductor = sourceScore.Conductors[index];

            writer.WriteLine("		EventConductorData data");

            var absTime = ScoreCompileHelper.TicksToSeconds(conductor.Ticks, sourceScore.Conductors);

            writer.WriteLine("			double absTime = "+ absTime.ToString(CultureInfo.InvariantCulture));
            writer.WriteLine("			UInt8 selected = 0");
            writer.WriteLine("			SInt64 tick = "+ conductor.Ticks.ToString());
            writer.WriteLine("			int measure = "+ conductor.Measure.ToString());
            writer.WriteLine("			int beat = "+ conductor.Beat.ToString());
            writer.WriteLine("			int track = 0");
            writer.WriteLine("			double tempo = "+ conductor.Tempo.ToString(CultureInfo.InvariantCulture));
            writer.WriteLine("			int tsigNumerator = "+ conductor.SignatureNumerator.ToString());
            writer.WriteLine("			int tsigDenominator = "+ conductor.SignatureDenominator.ToString());
            writer.WriteLine("			string marker = \"\"");
        }
Пример #2
0
        private static SourceScore ToSourceScore(ScoreObject scoreObject, ReadSourceOptions options)
        {
            var score = new SourceScore();

            var scoreIndex = options.ScoreIndex;
            var difficulty = (Difficulty)scoreIndex;
            var trackType  = ScoreHelper.MapDifficultyToTrackType(difficulty);
            var tracks     = ScoreHelper.GetTrackIndicesFromTrackType(trackType);

            score.Notes = scoreObject.NoteEvents
                          .Where(nd => Array.IndexOf(tracks, nd.Track) >= 0)
                          .Select(n => ToNote(n, tracks))
                          .Where(n => n != null).ToArray();
            score.Conductors  = scoreObject.ConductorEvents.Select(ToConductor).ToArray();
            score.MusicOffset = scoreObject.BgmOffset;

            score.ScoreIndex = scoreIndex;
            score.TrackCount = tracks.Length;

            return(score);
        }
        private static SourceNote[] GeneratePhantomNotes([NotNull] SourceScore sourceScore)
        {
            var result = new List <SourceNote>();

            var maxMeasure  = 224;
            var ticksFactor = NoteBase.TicksPerBeat / 8;

            for (var measure = 0; measure <= maxMeasure; ++measure)
            {
                var primary = new SourceNote {
                    TrackIndex = -1,
                    Type       = (NoteType)(-1),
                    Speed      = 1,
                    Measure    = measure + 1,
                    Beat       = 1,
                    Ticks      = 1920 * measure * ticksFactor
                };

                result.Add(primary);

                for (var j = 2; j <= 4; ++j)
                {
                    var secondary = new SourceNote {
                        TrackIndex = -1,
                        Type       = (NoteType)(-2),
                        Speed      = 1,
                        Measure    = measure + 1,
                        Beat       = j,
                        Ticks      = primary.Ticks + (480 * (j - 1)) * ticksFactor
                    };

                    result.Add(secondary);
                }
            }

            return(result.ToArray());
        }
        public static void FixNoteTickInfo([NotNull] NoteBase note, [NotNull] SourceScore sourceScore)
        {
            var baseConductor = sourceScore.Conductors[0];

            // For a properly-designed beatmap, the extra measure count SHOULD be an integer.
            // Otherwise you need to move your music start to make it on a beat.
            var extraMeasures = (int)Math.Round(sourceScore.MusicOffset / (60 / baseConductor.Tempo) / baseConductor.SignatureDenominator);

            var tickDiff = NoteBase.TicksPerBeat * 60 * extraMeasures * baseConductor.SignatureDenominator;

            note.Measure += extraMeasures;
            note.Ticks   += tickDiff;

            if (note is SourceNote n)
            {
                if (n.FollowingNotes != null && n.FollowingNotes.Length > 0)
                {
                    foreach (var fn in n.FollowingNotes)
                    {
                        fn.Ticks += tickDiff;
                    }
                }
            }
        }
Пример #5
0
 public void WriteSourceScore(Stream stream, string fileName, SourceScore score)
 {
     throw new NotSupportedException();
 }
Пример #6
0
        /// <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
            });
        }
Пример #7
0
 /// <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));
 }
        private static void WriteEventNote([NotNull] this TextWriter writer, [NotNull] SourceScore sourceScore, [NotNull, ItemNotNull] SourceNote[] notes, int index, TrackType trackType)
        {
            writer.WriteLine($"		[{index}]");

            var sourceNote = notes[index];

            writer.WriteLine("		EventNoteData data");

            // MLTD: "offset > 0" means music is AFTER the beatmap
            // MilliSim: "offset > 0" means music is BEFORE the beatmap
            var absTime = ScoreCompileHelper.TicksToSeconds(sourceNote.Ticks, sourceScore.Conductors);

            writer.WriteLine("			double absTime = "+ absTime.ToString(CultureInfo.InvariantCulture));
            writer.WriteLine("			UInt8 selected = 0");
            writer.WriteLine("			SInt64 tick = "+ (sourceNote.Ticks / (NoteBase.TicksPerBeat / 8)).ToString());

            if (sourceNote.Type < 0)
            {
                writer.WriteLine("			int measure = "+ sourceNote.Measure.ToString());
                writer.WriteLine("			int beat = "+ sourceNote.Beat.ToString());

                writer.WriteLine("			int track = -1");
            }
            else
            {
                writer.WriteLine("			int measure = 0");
                writer.WriteLine("			int beat = 0");

                var tracks = MltdHelper.GetTrackIndicesFromTrackType(trackType);

                writer.WriteLine("			int track = "+ tracks[sourceNote.TrackIndex].ToString());
            }

            writer.WriteLine("			int type = "+ ((int)MltdHelper.GetMltdNoteType(sourceNote)).ToString());
            writer.WriteLine("			float startPosx = "+ sourceNote.StartX.ToString(CultureInfo.InvariantCulture));
            writer.WriteLine("			float endPosx = "+ sourceNote.EndX.ToString(CultureInfo.InvariantCulture));
            writer.WriteLine("			float speed = "+ sourceNote.Speed.ToString(CultureInfo.InvariantCulture));

            if (sourceNote.FollowingNotes != null && sourceNote.FollowingNotes.Length > 0)
            {
                var duration = (int)((sourceNote.FollowingNotes[sourceNote.FollowingNotes.Length - 1].Ticks - sourceNote.Ticks) / (NoteBase.TicksPerBeat / 8));
                writer.WriteLine("			int duration = "+ duration.ToString());
            }
            else
            {
                writer.WriteLine("			int duration = 0");
            }

            writer.WritePolyPoints(sourceNote, sourceNote.FollowingNotes);

            if (sourceNote.FollowingNotes != null && sourceNote.FollowingNotes.Length > 0)
            {
                writer.WriteLine("			int endType = "+ ((int)sourceNote.FollowingNotes[sourceNote.FollowingNotes.Length - 1].FlickDirection).ToString());
            }
            else
            {
                writer.WriteLine("			int endType = 0");
            }

            if (sourceNote.Type < 0)
            {
                writer.WriteLine("			double leadTime = 0");
            }
            else
            {
                // TODO: What is this "magic number"?
                const double someConstant = 198.3471011848414;
                var          bpm          = ScorePreprocessor.GetCurrentBpm(sourceNote.Ticks, sourceScore.Conductors);
                var          leadTime     = someConstant / bpm;
                // TODO: Another guess... Didn't look too carefully inside speed variated notes.
                leadTime /= sourceNote.Speed;
                writer.WriteLine("			double leadTime = "+ leadTime.ToString(CultureInfo.InvariantCulture));
            }
        }
Пример #9
0
 public RuntimeScore Compile(SourceScore score, ScoreCompileOptions compileOptions)
 {
     compileOptions.Offset = (float)score.MusicOffset;
     return(ScoreCompileHelper.CompileScore(score, compileOptions));
 }
        public SourceScore ReadSourceScore(Stream stream, string fileName, ReadSourceOptions sourceOptions)
        {
            var lines = ReadLines(stream);

            var c = 0;

            var offsetTimeSpan = TimeSpan.Parse(lines[c]);

            ++c;

            var leadTimeSpan = TimeSpan.Parse(lines[c]);

            ++c;

            var trackCount = Convert.ToInt32(lines[c]);

            ++c;

            var beatsPerMeasure = Convert.ToInt32(lines[c]);

            ++c;

            // splitter
            ++c;

            var notes = new List <SourceNote>();

            while (!lines[c].StartsWith("---"))
            {
                var line = lines[c];

                SourceNote[] sourceNotes;
                if (TapPattern.IsMatch(line))
                {
                    var tap = Tap.FromString(line);

                    var sourceNote = new SourceNote {
                        Type = NoteType.Tap
                    };
                    FillHeader(sourceNote, tap.Header);
                    sourceNote.Size = StrToSize(tap.Body.Size);

                    sourceNotes = new[] { sourceNote };
                }
                else if (HoldPairPattern.IsMatch(line))
                {
                    var holds = Hold.CreateHolds(line);

                    var sourceNote = new SourceNote {
                        Type = NoteType.Hold
                    };
                    FillHeader(sourceNote, holds[0].Header);
                    sourceNote.Size = StrToSize(holds[0].Body.Size);

                    var holdEnd = new SourceNote {
                        Type = NoteType.Hold
                    };
                    FillHeader(holdEnd, holds[1].Header);
                    holdEnd.Size           = sourceNote.Size;
                    holdEnd.FlickDirection = StrToDirection(holds[1].Body.Direction);

                    sourceNote.FollowingNotes = new[] { holdEnd };

                    sourceNotes = new[] { sourceNote };
                }
                else if (FlickPattern.IsMatch(line))
                {
                    var flick = Flick.FromString(line);

                    var sourceNote = new SourceNote {
                        Type = NoteType.Flick
                    };
                    FillHeader(sourceNote, flick.Header);
                    sourceNote.Size           = StrToSize(flick.Body.Size);
                    sourceNote.FlickDirection = StrToDirection(flick.Body.Direction);

                    sourceNotes = new[] { sourceNote };
                }
                else if (SlideSeriesPattern.IsMatch(line))
                {
                    var slides = Slide.CreateSlides(line);

                    var sourceNote = new SourceNote {
                        Type = NoteType.Slide
                    };
                    FillHeader(sourceNote, slides[0].Header);

                    var following = new List <SourceNote>();
                    for (var i = 1; i < slides.Count; ++i)
                    {
                        var nodeInSeries = new SourceNote {
                            Type = NoteType.Slide
                        };
                        FillHeader(nodeInSeries, slides[i].Header);

                        if (i == slides.Count - 1)
                        {
                            nodeInSeries.FlickDirection = StrToDirection(slides[i].Body.Direction);
                        }

                        following.Add(nodeInSeries);
                    }

                    sourceNote.FollowingNotes = following.ToArray();

                    sourceNotes = new[] { sourceNote };
                }
                else if (SpecialPattern.IsMatch(line))
                {
                    var special = Special.FromString(line);

                    var sourceNote = new SourceNote {
                        Type = NoteType.Special
                    };
                    FillHeader(sourceNote, special.Header);

                    sourceNotes = new[] { sourceNote };
                }
                else
                {
                    throw new FormatException("Error in simple format.");
                }

                notes.AddRange(sourceNotes);

                // next line
                ++c;
            }

            // Sort the added notes.
            notes.Sort((n1, n2) => n1.Ticks.CompareTo(n2.Ticks));

            // splitter
            ++c;

            var conductors = new List <Conductor>();

            for (; c < lines.Count; ++c)
            {
                var ss           = lines[c].Split(':');
                var measureIndex = Convert.ToInt32(ss[0]);
                var bpm          = Convert.ToDouble(ss[1]);
                var conductor    = new Conductor {
                    Measure              = measureIndex - 1,
                    Tempo                = bpm,
                    Ticks                = (measureIndex - 1) * beatsPerMeasure * NoteBase.TicksPerBeat,
                    SignatureNumerator   = beatsPerMeasure,
                    SignatureDenominator = beatsPerMeasure
                };
                conductors.Add(conductor);
            }

            conductors.Sort((n1, n2) => n1.Ticks.CompareTo(n2.Ticks));

            var score = new SourceScore();

            score.Conductors  = conductors.ToArray();
            score.Notes       = notes.ToArray();
            score.TrackCount  = trackCount;
            score.MusicOffset = offsetTimeSpan.TotalSeconds;
            return(score);

            void FillHeader(SourceNote note, NoteHeader header)
            {
                var fraction = (float)(header.Nominator - 1) / header.Denominator;

                note.Beat       = (int)(beatsPerMeasure * fraction);
                note.StartX     = header.Start - 1;
                note.EndX       = header.End - 1;
                note.Speed      = header.Speed;
                note.LeadTime   = leadTimeSpan.TotalSeconds;
                note.Measure    = header.Measure - 1;
                note.Ticks      = 60 * (long)(beatsPerMeasure * ((header.Measure - 1) + fraction) * NoteBase.TicksPerBeat);
                note.TrackIndex = (int)note.StartX;

                if (note.TrackIndex < 0 || note.TrackIndex >= trackCount)
                {
                    Debug.Print("Warning: Invalid track index \"{0}\", changing into range [0, {1}].", note.TrackIndex, trackCount - 1);

                    if (note.TrackIndex < 0)
                    {
                        note.TrackIndex = 0;
                    }
                    else if (note.TrackIndex >= trackCount)
                    {
                        note.TrackIndex = trackCount - 1;
                    }
                }
            }

            NoteSize StrToSize(string str)
            {
                if (string.IsNullOrEmpty(str))
                {
                    return(NoteSize.Small);
                }
                else
                {
                    switch (str)
                    {
                    case "small":
                        return(NoteSize.Small);

                    case "large":
                        return(NoteSize.Large);

                    default:
                        throw new ArgumentOutOfRangeException(nameof(str), str, null);
                    }
                }
            }

            FlickDirection StrToDirection(string str)
            {
                if (string.IsNullOrEmpty(str))
                {
                    return(FlickDirection.None);
                }
                else
                {
                    switch (str)
                    {
                    case "left":
                        return(FlickDirection.Left);

                    case "right":
                        return(FlickDirection.Right);

                    case "up":
                        return(FlickDirection.Up);

                    default:
                        throw new ArgumentOutOfRangeException(nameof(str), str, null);
                    }
                }
            }
        }
Пример #11
0
        private static SourceScore ToSourceScore([NotNull] Project project, [NotNull] Score score, [NotNull] ReadSourceOptions options)
        {
            var result = new SourceScore();

            var sourceNotes = new List <SourceNote>();
            var conductors  = new List <Conductor>();

            const int beatsPerMeasure = 4;

            var globalConductor = new Conductor();

            globalConductor.Tempo = (float)project.Settings.BeatPerMinute;
            globalConductor.SignatureNumerator   = project.Settings.Signature;
            globalConductor.SignatureDenominator = beatsPerMeasure;

            conductors.Add(globalConductor);

            var allNotes = score.GetAllNotes();

            foreach (var note in allNotes)
            {
                SourceNote sourceNote = null;
                Conductor  conductor  = null;

                switch (note.Basic.Type)
                {
                case NoteType.TapOrFlick:
                    sourceNote = new SourceNote();
                    FillTapOrFlick(note, sourceNote);
                    break;

                case NoteType.Hold:
                    if (!note.Helper.IsHoldStart)
                    {
                        continue;
                    }

                    sourceNote = new SourceNote();
                    FillHold(note, sourceNote);
                    break;

                case NoteType.Slide:
                    if (!note.Helper.IsSlideStart)
                    {
                        continue;
                    }

                    sourceNote = new SourceNote();
                    FillSlide(note, sourceNote);
                    break;

                case NoteType.VariantBpm: {
                    conductor = new Conductor();

                    FillCommonProperties(note, conductor);

                    Debug.Assert(note.Params != null, "note.Params != null");

                    conductor.Tempo = (float)note.Params.NewBpm;
                    conductor.SignatureNumerator   = project.Settings.Signature;
                    conductor.SignatureDenominator = beatsPerMeasure;
                }
                break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (sourceNote != null)
                {
                    sourceNotes.Add(sourceNote);
                }

                if (conductor != null)
                {
                    conductors.Add(conductor);
                }
            }

            result.MusicOffset = project.Settings.StartTimeOffset;
            result.TrackCount  = CgssTrackCount;
            result.ScoreIndex  = options.ScoreIndex;

            sourceNotes.Sort((n1, n2) => n1.Ticks.CompareTo(n2.Ticks));
            conductors.Sort((n1, n2) => n1.Ticks.CompareTo(n2.Ticks));

            result.Notes      = sourceNotes.ToArray();
            result.Conductors = conductors.ToArray();

            return(result);

            void FillCommonProperties(Note note, NoteBase sourceNote)
            {
                var bar = note.Basic.Bar;

                sourceNote.Measure = bar.Basic.Index;

                var fraction = (float)note.Basic.IndexInGrid / bar.GetGridPerSignature() / beatsPerMeasure;

                sourceNote.Beat = (int)fraction;

                //sourceNote.GroupID = 0;

                sourceNote.Ticks = 60 * (long)(beatsPerMeasure * (sourceNote.Measure + fraction) * NoteBase.TicksPerBeat);
            }

            void FillSourceNoteProperties(Note note, SourceNote sourceNote)
            {
                FillCommonProperties(note, sourceNote);

                sourceNote.Size  = NoteSize.Small;
                sourceNote.Speed = 1.0f;

                sourceNote.StartX     = (float)(note.Basic.StartPosition - 1);
                sourceNote.EndX       = (float)(note.Basic.FinishPosition - 1);
                sourceNote.TrackIndex = (int)sourceNote.StartX;

                if (sourceNote.TrackIndex < 0 || sourceNote.TrackIndex > (CgssTrackCount - 1))
                {
                    Debug.Print("Warning: Invalid track index \"{0}\", changing into range [0, {1}].", sourceNote.TrackIndex, CgssTrackCount - 1);

                    if (sourceNote.TrackIndex < 0)
                    {
                        sourceNote.TrackIndex = 0;
                    }
                    else if (sourceNote.TrackIndex > (CgssTrackCount - 1))
                    {
                        sourceNote.TrackIndex = (CgssTrackCount - 1);
                    }
                }

                sourceNote.LeadTime = (float)DefaultLeadTime.TotalSeconds;
            }

            void FillTapOrFlick(Note note, SourceNote sourceNote)
            {
                FillSourceNoteProperties(note, sourceNote);

                switch (note.Basic.FlickType)
                {
                case NoteFlickType.None:
                    sourceNote.Type           = MilliSim.Contributed.Scores.NoteType.Tap;
                    sourceNote.FlickDirection = FlickDirection.None;
                    break;

                case NoteFlickType.Left:
                    sourceNote.Type           = MilliSim.Contributed.Scores.NoteType.Flick;
                    sourceNote.FlickDirection = FlickDirection.Left;
                    break;

                case NoteFlickType.Right:
                    sourceNote.Type           = MilliSim.Contributed.Scores.NoteType.Flick;
                    sourceNote.FlickDirection = FlickDirection.Right;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            void FillHold(Note note, SourceNote sourceNote)
            {
                FillSourceNoteProperties(note, sourceNote);

                sourceNote.Type = MilliSim.Contributed.Scores.NoteType.Hold;

                var holdEnd = new SourceNote();

                Debug.Assert(note.Editor.HoldPair != null, "note.Editor.HoldPair != null");

                FillSourceNoteProperties(note.Editor.HoldPair, holdEnd);

                holdEnd.Type = MilliSim.Contributed.Scores.NoteType.Hold;

                switch (note.Editor.HoldPair.Basic.FlickType)
                {
                case NoteFlickType.None:
                    holdEnd.FlickDirection = FlickDirection.None;
                    break;

                case NoteFlickType.Left:
                    holdEnd.FlickDirection = FlickDirection.Left;
                    break;

                case NoteFlickType.Right:
                    holdEnd.FlickDirection = FlickDirection.Right;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                sourceNote.FollowingNotes = new[] { holdEnd };
            }

            void FillSlide(Note note, SourceNote sourceNote)
            {
                FillSourceNoteProperties(note, sourceNote);

                sourceNote.Type = MilliSim.Contributed.Scores.NoteType.Slide;

                var following = new List <SourceNote>();

                var nextSlideNode = note.Editor.NextSlide;

                while (nextSlideNode != null)
                {
                    var node = new SourceNote();

                    FillSourceNoteProperties(nextSlideNode, node);

                    node.Type = MilliSim.Contributed.Scores.NoteType.Slide;

                    if (nextSlideNode.Helper.IsSlideEnd)
                    {
                        switch (nextSlideNode.Basic.FlickType)
                        {
                        case NoteFlickType.None:
                            node.FlickDirection = FlickDirection.None;
                            break;

                        case NoteFlickType.Left:
                            node.FlickDirection = FlickDirection.Left;
                            break;

                        case NoteFlickType.Right:
                            node.FlickDirection = FlickDirection.Right;
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                    }

                    following.Add(node);

                    nextSlideNode = nextSlideNode.Editor.NextSlide;
                }

                sourceNote.FollowingNotes = following.ToArray();
            }
        }
Пример #12
0
        /**
         * A demonstration of the usage of ScoreCompilerHelper methods.
         */

        private RuntimeScore MyCompile(SourceScore score, ScoreCompileOptions compileOptions)
        {
            return(ScoreCompileHelper.CompileScore(score, compileOptions, CreateNotes));
        }
Пример #13
0
 /// <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));
 }
        private static void WriteNotes([NotNull] this TextWriter writer, [NotNull] SourceScore score, [NotNull] ScenarioScrObj template)
        {
            var notes    = score.Notes;
            var noteList = new List <EventScenarioData>();

            var specialNote = notes.FirstOrDefault(n => n.Type == NoteType.Special);

            // Mofify time: the tap buttons animation before the special note (the big round note)
            if (specialNote != null)
            {
                noteList.AddRange(template.scenario);

                var animNote = noteList.Find(n => n.type == ScenarioNoteType.BeginTapButtonsAnimation);

                if (animNote != null)
                {
                    var specialNoteTime = ScoreCompileHelper.TicksToSeconds(specialNote.Ticks, score.Conductors);

                    animNote.absTime = specialNoteTime - 0.5f;
                    animNote.tick    = ScorePreprocessor.SecondsToTicks(animNote.absTime, score.Conductors);
                }

                // Modify time: second tap buttons appearing time (the one that is after the special note)
                var reappearNote = notes.FirstOrDefault(n => n.Ticks > specialNote.Ticks);

                if (reappearNote != null && animNote != null)
                {
                    var reaNote = noteList.Where(n => n.type == ScenarioNoteType.ShowTapButtons).Skip(1).FirstOrDefault();

                    if (reaNote != null)
                    {
                        var reappearNoteTime = ScoreCompileHelper.TicksToSeconds(reappearNote.Ticks, score.Conductors);

                        reaNote.absTime = reappearNoteTime - 0.8f;
                        reaNote.tick    = ScorePreprocessor.SecondsToTicks(reaNote.absTime, score.Conductors);
                    }
                }
            }

            noteList.Sort((n1, n2) => {
                var t = n1.tick.CompareTo(n2.tick);

                if (t != 0)
                {
                    return(t);
                }

                t = ((int)n1.type).CompareTo((int)n2.type);

                if (t != 0)
                {
                    return(t);
                }

                t = n1.idol.CompareTo(n2.idol);

                if (t != 0)
                {
                    return(t);
                }

                return(n1.track.CompareTo(n2.track));
            });

            writer.Write(@"EventScenarioData scenario
	Array Array
	int size = "    );
            writer.WriteLine(noteList.Count.ToString());

            for (var i = 0; i < noteList.Count; ++i)
            {
                var sn = noteList[i];

                writer.WriteLine("		[{0}]", i.ToString());
                writer.WriteScenarioNote(2, "data", sn);
            }
        }
Пример #15
0
        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();
        }
Пример #16
0
        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}");
                }
            }
        }