Example #1
0
 // Start is called before the first frame update
 void Start()
 {
     objectContainerCollections = GetComponents <BeatmapObjectContainerCollection>()
                                  .Where(x => x is NotesContainer || x is ObstaclesContainer).ToList();
     BeatmapObjectContainer.FlaggedForDeletionEvent += FlaggedForDeletion;
     Settings.NotifyBySettingName("RotateTrack", UpdateRotateTrack);
     songTimeInBeats = atsc.GetBeatFromSeconds(BeatSaberSongContainer.Instance.loadedSong.length);
 }
    // Start is called before the first frame update
    IEnumerator Start()
    {
        yield return(new WaitForSeconds(0.1f)); //wait for ATSC to get song info, so we can get beats in the song VVV

        measureTextsByBeat.Add(0, measureLinePrefab);
        previousEnabledByBeat.Add(0, true);
        for (int i = 1; i <= Mathf.FloorToInt(atsc.GetBeatFromSeconds(BeatSaberSongContainer.Instance.loadedSong.length)); i++)
        {
            TextMeshProUGUI instantiate = Instantiate(measureLinePrefab, parent);
            instantiate.text = $"{i}";
            instantiate.transform.localPosition = new Vector3(0, i * EditorScaleController.EditorScale, 0);
            measureTextsByBeat.Add(i, instantiate);
            previousEnabledByBeat.Add(i, true);
        }
        init = true;
    }
    public void RefreshMeasureLines()
    {
        Debug.Log("Refreshing measure lines...");
        init = false;
        Queue <TextMeshProUGUI> existing = new Queue <TextMeshProUGUI>(measureTextsByBeat.Values);

        measureTextsByBeat.Clear();
        previousEnabledByBeat.Clear();

        int   rawBeatsInSong = Mathf.FloorToInt(atsc.GetBeatFromSeconds(BeatSaberSongContainer.Instance.loadedSong.length));
        float jsonBeat       = 0;
        int   modifiedBeats  = 0;
        float songBPM        = BeatSaberSongContainer.Instance.song.beatsPerMinute;

        List <BeatmapBPMChange> allBPMChanges = new List <BeatmapBPMChange>()
        {
            new BeatmapBPMChange(songBPM, 0)
        };

        allBPMChanges.AddRange(bpmChangesContainer.LoadedObjects.Cast <BeatmapBPMChange>());

        while (jsonBeat <= rawBeatsInSong)
        {
            TextMeshProUGUI text = existing.Count > 0 ? existing.Dequeue() : Instantiate(measureLinePrefab, parent);
            text.text = $"{modifiedBeats}";
            text.transform.localPosition = new Vector3(0, jsonBeat * EditorScaleController.EditorScale, 0);
            measureTextsByBeat.Add(jsonBeat, text);
            previousEnabledByBeat.Add(jsonBeat, true);

            modifiedBeats++;
            BeatmapBPMChange last = allBPMChanges.Last(x => x._Beat <= modifiedBeats);
            jsonBeat = ((modifiedBeats - last._Beat) / last._BPM * songBPM) + last._time;
        }

        // Set proper spacing between Notes grid, Measure lines, and Events grid
        measureLinesGridChild.Size = modifiedBeats > 1000 ? 1 : 0;
        foreach (TextMeshProUGUI leftovers in existing)
        {
            Destroy(leftovers.gameObject);
        }
        init = true;
        RefreshVisibility();
        RefreshPositions();
    }
    public void RefreshMeasureLines()
    {
        init = false;
        Queue <TextMeshProUGUI> existing = new Queue <TextMeshProUGUI>(measureTextsByBeat.Values);

        measureTextsByBeat.Clear();
        previousEnabledByBeat.Clear();
        int              rawBeatsInSong          = Mathf.FloorToInt(atsc.GetBeatFromSeconds(BeatSaberSongContainer.Instance.loadedSong.length));
        float            beatsProcessed          = 1;
        float            rawBPMtoChangedBPMRatio = 1;
        int              modifiedBeats           = 1;
        BeatmapBPMChange lastBPMChange           = null;

        while (beatsProcessed <= rawBeatsInSong)
        {
            TextMeshProUGUI text = existing.Count > 0 ? existing.Dequeue() : Instantiate(measureLinePrefab, parent);
            text.gameObject.SetActive(true);
            text.text = $"{modifiedBeats}";
            text.transform.localPosition = new Vector3(0, beatsProcessed * EditorScaleController.EditorScale, 0);
            measureTextsByBeat.Add(beatsProcessed, text);
            previousEnabledByBeat.Add(beatsProcessed, true);

            modifiedBeats++;
            BeatmapBPMChange last = bpmChangesContainer.FindLastBPM(beatsProcessed + rawBPMtoChangedBPMRatio, true);
            if (last != lastBPMChange && last?._BPM > 0)
            {
                lastBPMChange           = last;
                beatsProcessed          = last._time;
                rawBPMtoChangedBPMRatio = BeatSaberSongContainer.Instance.song.beatsPerMinute / last._BPM;
            }
            else
            {
                beatsProcessed += rawBPMtoChangedBPMRatio;
            }
        }
        foreach (TextMeshProUGUI leftovers in existing)
        {
            Destroy(leftovers.gameObject);
        }
        init = true;
        RefreshVisibility();
        RefreshPositions();
    }
Example #5
0
    void PlaySound(bool initial, int index, BeatmapObject objectData)
    {
        // Filter notes that are too far behind the current beat
        // (Commonly occurs when Unity freezes for some unrelated f*****g reason)
        if (objectData._time - container.AudioTimeSyncController.CurrentBeat <= -0.5f)
        {
            return;
        }

        //actual ding stuff
        if (objectData._time == lastCheckedTime || !NoteTypeToDing[((BeatmapNote)objectData)._type])
        {
            return;
        }

        /*
         * As for why we are not using "initial", it is so notes that are not supposed to ding do not prevent notes at
         * the same time that are supposed to ding from triggering the sound effects.
         */
        lastCheckedTime = objectData._time;
        var soundListId = Settings.Instance.NoteHitSound;
        var list        = soundLists[soundListId];

        var shortCut = false;

        if (index - DensityCheckOffset > 0 && index + DensityCheckOffset < container.LoadedObjects.Count)
        {
            BeatmapObject first  = container.LoadedObjects.ElementAt(index + DensityCheckOffset);
            BeatmapObject second = container.LoadedObjects.ElementAt(index - DensityCheckOffset);
            if (first != null && second != null)
            {
                if (first._time - objectData._time <= ThresholdInNoteTime && objectData._time - second._time <= ThresholdInNoteTime)
                {
                    shortCut = true;
                }
            }
        }

        var timeUntilDing = objectData._time - atsc.GetBeatFromSeconds(atsc.songAudioSource.time);
        var hitTime       = (atsc.GetSecondsFromBeat(timeUntilDing) / songSpeed) - offset;

        audioUtil.PlayOneShotSound(list.GetRandomClip(shortCut), Settings.Instance.NoteHitVolume, 1, hitTime);
    }
Example #6
0
    private void CreateAutogeneratedBPMChange(int res)
    {
        if (res == 2)
        {
            return;
        }
        Settings.Instance.Reminder_UnsupportedEditorOffset = res == 0;

        float offset = BeatSaberSongContainer.Instance.difficultyData.customData["_editorOffset"];

        BeatSaberSongContainer.Instance.difficultyData.customData.Remove("_editorOffset");
        BeatSaberSongContainer.Instance.difficultyData.customData.Remove("_editorOldOffset");

        BeatmapBPMChange autoGenerated = new BeatmapBPMChange(
            BeatSaberSongContainer.Instance.song.beatsPerMinute,
            AudioTimeSyncController.GetBeatFromSeconds(offset / 1000f));

        autoGenerated._customData = new SimpleJSON.JSONObject();
        autoGenerated._customData.Add("__note", "Autogenerated by ChroMapper");

        SpawnObject(autoGenerated, true, false);
        RefreshGridShaders();
        RefreshPool(true);
    }