示例#1
0
    void UpdateBeatLines4()
    {
        int measurePoolPos = 0, beatPoolPos = 0, quarterPoolPos = 0;

        Song song           = editor.currentSong;
        uint startRange     = song.WorldPositionToSnappedTick(editor.camYMin.position.y, 8);
        uint endRange       = editor.maxPos;
        var  timeSignatures = editor.currentSong.timeSignatures;
        int  startIndex     = SongObjectHelper.FindClosestPositionRoundedDown(startRange, timeSignatures);

        for (int tsIndex = startIndex; tsIndex < timeSignatures.Count && timeSignatures[tsIndex].tick <= endRange; ++tsIndex)
        {
            TimeSignature ts = timeSignatures[tsIndex];

            uint nextTSTick = tsIndex + 1 < timeSignatures.Count ? timeSignatures[tsIndex + 1].tick : endRange;

            TimeSignature.MeasureInfo measureInfo = ts.GetMeasureInfo();

            measurePoolPos += RenderBeatLines(ts, measureInfo.measureLine, measureLinePool, measurePoolPos, startRange, endRange, nextTSTick);
            beatPoolPos    += RenderBeatLines(ts, measureInfo.beatLine, beatLinePool, beatPoolPos, startRange, endRange, nextTSTick);
            quarterPoolPos += RenderBeatLines(ts, measureInfo.quarterBeatLine, quarterBeatLinePool, quarterPoolPos, startRange, endRange, nextTSTick);
        }

        DisableBeatLines(measurePoolPos, measureLinePool);
        DisableBeatLines(beatPoolPos, beatLinePool);
        DisableBeatLines(quarterPoolPos, quarterBeatLinePool);
    }
    // Should be called once the physics system has settled down
    void Init()
    {
        ChartEditor editor = ChartEditor.Instance;

        Debug.Assert(!hitWindowFeeder.enabled);
        hitWindowFeeder.enabled = true;

        if (botEnabled)
        {
            // We want the bot to automatically hit any sustains that are currently active in the view, but for which the notes are already past the strikeline
            Song  song        = editor.currentSong;
            float currentTime = editor.currentVisibleTime;
            uint  currentTick = song.TimeToTick(currentTime, song.resolution);
            int   index       = SongObjectHelper.FindClosestPositionRoundedDown(currentTick, editor.currentChart.notes);
            if (index != SongObjectHelper.NOTFOUND)
            {
                Note        note         = editor.currentChart.notes[index];
                List <Note> sustainNotes = new List <Note>();
                NoteFunctions.GetPreviousOfSustains(sustainNotes, note, GameSettings.extendedSustainsEnabled);

                foreach (Note chordNote in note.chord)
                {
                    sustainNotes.Add(chordNote);
                }
                foreach (Note sustainNote in sustainNotes)
                {
                    if (sustainNote.controller != null)
                    {
                        hitWindowFeeder.TryAddNote(sustainNote.controller);
                    }
                }
            }
        }
    }
示例#3
0
    // Calculate the beat lines directly from the time signature positions themselves
    void UpdateBeatLines3()
    {
        int measurePoolPos = 0, beatPoolPos = 0, quarterPoolPos = 0;

        Song song                       = editor.currentSong;
        uint startRange                 = song.WorldPositionToSnappedTick(editor.camYMin.position.y, 8);
        uint endRange                   = editor.maxPos;
        var  timeSignatures             = editor.currentSong.timeSignatures;
        uint standardMeasureLengthTicks = (uint)(Song.RESOLUTIONS_PER_MEASURE * song.resolution);

        int startIndex = SongObjectHelper.FindClosestPositionRoundedDown(startRange, timeSignatures);

        for (int tsIndex = startIndex; tsIndex < timeSignatures.Count && timeSignatures[tsIndex].tick <= endRange; ++tsIndex)
        {
            TimeSignature ts            = timeSignatures[tsIndex];
            uint          nextTick      = ts.tick;
            uint          nextTSTick    = tsIndex + 1 < timeSignatures.Count ? timeSignatures[tsIndex + 1].tick : endRange;
            float         beatDeltaTick = standardMeasureLengthTicks / ts.beatsPerMeasure;

            uint startDeltaFromTSTick = startRange > ts.tick ? (startRange - ts.tick) : 0;
            int  quarterLineIndex     = (int)Mathf.Round((float)(startDeltaFromTSTick) / beatDeltaTick); // Jump to the next reasonable line index rather than looping until we get there
            if (quarterLineIndex > 0)
            {
                --quarterLineIndex;
            }

            while (nextTick < nextTSTick && nextTick <= endRange)
            {
                uint currentTick   = nextTick;
                bool tickIsMeasure = quarterLineIndex % ts.quarterNotesPerMeasure == 0;

                if (currentTick >= startRange && currentTick < nextTSTick && currentTick <= endRange)
                {
                    if (tickIsMeasure)
                    {
                        SetBeatLinePosition(currentTick, measureLinePool, ref measurePoolPos);
                    }
                    else
                    {
                        SetBeatLinePosition(currentTick, beatLinePool, ref beatPoolPos);
                    }
                }

                nextTick = ts.tick + (uint)Mathf.Round(beatDeltaTick * (++quarterLineIndex));

                uint tickDelta   = nextTick - currentTick;
                uint newPosition = currentTick + tickDelta / 2;

                if (newPosition >= startRange && newPosition < nextTSTick && newPosition <= endRange)
                {
                    SetBeatLinePosition(newPosition, quarterBeatLinePool, ref quarterPoolPos);
                }
            }
        }

        DisableBeatLines(measurePoolPos, measureLinePool);
        DisableBeatLines(beatPoolPos, beatLinePool);
        DisableBeatLines(quarterPoolPos, quarterBeatLinePool);
    }
        public SongObjectTracker(SongObjectCache <T> objects, uint startTick)
        {
            this.objects = objects;

            // Skip ahead to where we're actually going to start
            int startIndex = SongObjectHelper.FindClosestPositionRoundedDown(startTick, objects);

            if (startIndex != SongObjectHelper.NOTFOUND)
            {
                currentIndex = startIndex;
            }
        }
    public static uint TickToSnappedTick(uint tick, int step, Song song)
    {
        float resolution = song.resolution;

        var           timeSignatures = song.timeSignatures;
        int           tsIndex        = SongObjectHelper.FindClosestPositionRoundedDown(tick, timeSignatures);
        TimeSignature ts             = timeSignatures[tsIndex];
        uint?         endRange       = tsIndex < (timeSignatures.Count - 1) ? (uint?)timeSignatures[tsIndex + 1].tick : null;

        TimeSignature.MeasureInfo measureInfo     = ts.GetMeasureInfo();
        TimeSignature.BeatInfo    measureLineInfo = measureInfo.measureLine;
        TimeSignature.BeatInfo    beatLineInfo    = measureInfo.beatLine;

        uint tickOffsetFromTs     = tick - ts.tick;
        int  measuresFromTsToSnap = (int)((float)tickOffsetFromTs / measureLineInfo.tickGap);
        uint lastMeasureTick      = ts.tick + (uint)(measuresFromTsToSnap * measureLineInfo.tickGap);

        float realBeatStep = step / 4.0f;
        float tickGap      = beatLineInfo.tickGap / realBeatStep * ts.denominator / 4.0f;
        uint  tickOffsetFromLastMeasure  = tick - lastMeasureTick;
        int   beatsFromLastMeasureToSnap = Mathf.RoundToInt((float)tickOffsetFromLastMeasure / tickGap);

        uint snappedTick = lastMeasureTick + (uint)(beatsFromLastMeasureToSnap * tickGap);

        if (endRange.HasValue)
        {
            return(snappedTick < endRange.Value ? snappedTick : endRange.Value);
        }
        else
        {
            return(snappedTick);
        }

        // Old algorithm
        // Snap position based on step
        //float factor = Song.FULL_STEP / (float)step * resolution / Song.STANDARD_BEAT_RESOLUTION;
        //float divisor = tick / factor;
        //float lowerBound = (int)divisor * factor;
        //float remainder = divisor - (int)divisor;
        //
        //if (remainder > 0.5f)
        //    tick = (uint)Mathf.Round(lowerBound + factor);
        //else
        //    tick = (uint)Mathf.Round(lowerBound);
        //
        //return tick;
    }
    public static Note.SpecialType IsStarpower(Note note)
    {
        Note.SpecialType specialType = Note.SpecialType.None;

        int index = SongObjectHelper.FindClosestPositionRoundedDown(note.tick, note.chart.starPower);

        if (index != SongObjectHelper.NOTFOUND)
        {
            Starpower sp = note.chart.starPower[index];
            if (sp.tick == note.tick || (sp.tick <= note.tick && sp.tick + sp.length > note.tick))
            {
                specialType = Note.SpecialType.StarPower;
            }
        }

        return(specialType);
    }
示例#7
0
    public void Update()
    {
        ChartEditor editor = ChartEditor.Instance;
        float       time   = editor.currentVisibleTime;
        Song        song   = editor.currentSong;

        if (feederNoteIndex <= 0)
        {
            uint currentTick = song.TimeToTick(time, song.resolution);
            feederNoteIndex = SongObjectHelper.FindClosestPositionRoundedDown(currentTick, editor.currentChart.notes);
        }

        if (hitWindow != null && feederNoteIndex >= 0 && feederNoteIndex < editor.currentChart.notes.Count)
        {
            uint maxScanTick = editor.maxPos;
            int  noteIndex   = feederNoteIndex;

            while (noteIndex < editor.currentChart.notes.Count)
            {
                Note note = editor.currentChart.notes[noteIndex];
                if (note.tick > maxScanTick)
                {
                    break;
                }

                ++noteIndex;

                bool validControllerAttached = note.controller != null && note.controller.isActiveAndEnabled && !note.controller.hit;
                if (validControllerAttached && note.tick != lastAddedTick)
                {
                    if (!hitWindow.DetectEnter(note, time))
                    {
                        break;
                    }
                    else
                    {
                        lastAddedTick = note.tick;
                    }

                    feederNoteIndex = noteIndex;    // Only increase the feeder note index if we pass notes that are completely valid. The notes ahead may have simply not been loaded into view yet. Need to reproccess them once they do come into view
                }
            }
        }
    }
    uint CalculateNextBeatTickPosition(uint currentTickPosition)
    {
        Song song                       = editor.currentSong;
        var  timeSignatures             = editor.currentSong.timeSignatures;
        uint standardMeasureLengthTicks = (uint)(Song.RESOLUTIONS_PER_MEASURE * song.resolution);

        int           lastTsIndex          = SongObjectHelper.FindClosestPositionRoundedDown(currentTickPosition, timeSignatures);
        TimeSignature currentTimeSignature = timeSignatures[lastTsIndex];
        TimeSignature nextTimeSignature    = lastTsIndex + 1 < timeSignatures.Count ? timeSignatures[lastTsIndex + 1] : null;
        uint          tickOrigin           = currentTimeSignature.tick;
        float         beatDeltaTick        = standardMeasureLengthTicks / currentTimeSignature.beatsPerMeasure;

        if (nextTimeSignature != null && currentTickPosition + beatDeltaTick >= nextTimeSignature.tick)
        {
            return(nextTimeSignature.tick);
        }

        uint deltaTick = currentTickPosition - tickOrigin;
        uint remainder = (uint)Mathf.Round(deltaTick % beatDeltaTick);

        return(tickOrigin + deltaTick - remainder + (uint)Mathf.Round(beatDeltaTick));
    }