Exemple #1
0
    /// <summary>
    /// Converts a time value into a tick position value. May be inaccurate due to interger rounding.
    /// </summary>
    /// <param name="time">The time (in seconds) to convert.</param>
    /// <param name="resolution">Ticks per beat, usually provided from the resolution song of a Song class.</param>
    /// <returns>Returns the calculated tick position.</returns>
    public uint TimeToTick(float time, float resolution, bool capByLength = true)
    {
        if (time < 0)
        {
            time = 0;
        }
        else if (capByLength && time > length)
        {
            time = length;
        }

        uint position = 0;

        BPM prevBPM = bpms[0];

        // Search for the last bpm
        for (int i = 0; i < bpms.Count; ++i)
        {
            BPM bpmInfo = bpms[i];
            if (bpmInfo.assignedTime >= time)
            {
                break;
            }
            else
            {
                prevBPM = bpmInfo;
            }
        }

        position  = prevBPM.tick;
        position += TickFunctions.TimeToDis(prevBPM.assignedTime, time, resolution, prevBPM.value / 1000.0f);

        return(position);
    }
    // Update is called once per frame
    public void Update()
    {
        // Offset by audio calibration
        Vector3 pos = initLocalPos;

        pos.y += TickFunctions.TimeToWorldYPosition(GameSettings.audioCalibrationMS / 1000.0f * GameSettings.gameSpeed);
        transform.localPosition = pos;

        uint currentTickPos = editor.currentSong.WorldYPositionToTick(transform.position.y);

        if (Globals.applicationMode == Globals.ApplicationMode.Playing)
        {
            if (currentTickPos >= nextClapPos)
            {
                if (GameSettings.metronomeActive)
                {
                    sampleStream.volume = GameSettings.sfxVolume * GameSettings.vol_master;
                    sampleStream.pan    = GameSettings.audio_pan;
                    sampleStream.Play();
                }
            }
        }

        nextClapPos = CalculateNextBeatTickPosition(currentTickPos);
    }
Exemple #3
0
    public System.Collections.Generic.List <ActionHistory.Action> FixUpBPMAnchors()
    {
        System.Collections.Generic.List <ActionHistory.Action> record = new System.Collections.Generic.List <ActionHistory.Action>();

        var bpms = currentSong.bpms;

        // Fix up any anchors
        for (int i = 0; i < bpms.Count; ++i)
        {
            if (bpms[i].anchor != null && i > 0)
            {
                BPM anchorBPM   = bpms[i];
                BPM bpmToAdjust = bpms[i - 1];

                double deltaTime = (double)anchorBPM.anchor - bpmToAdjust.time;
                uint   newValue  = (uint)Mathf.Round((float)(TickFunctions.DisToBpm(bpmToAdjust.tick, anchorBPM.tick, deltaTime, currentSong.resolution) * 1000.0d));

                if (deltaTime > 0 && newValue > 0)
                {
                    if (bpmToAdjust.value != newValue)
                    {
                        BPM original = new BPM(bpmToAdjust);
                        bpmToAdjust.value      = newValue;
                        anchorBPM.assignedTime = currentSong.LiveTickToTime(anchorBPM.tick, currentSong.resolution);

                        record.Add(new ActionHistory.Modify(original, bpmToAdjust));
                    }
                }
            }
        }

        return(record);
    }
Exemple #4
0
    public static float LiveTickToTime(uint position, float resolution, BPM initialBpm, IList <SyncTrack> synctrack)
    {
        double time    = 0;
        BPM    prevBPM = initialBpm;

        foreach (SyncTrack syncTrack in synctrack)
        {
            BPM bpmInfo = syncTrack as BPM;

            if (bpmInfo == null)
            {
                continue;
            }

            if (bpmInfo.tick > position)
            {
                break;
            }
            else
            {
                time   += TickFunctions.DisToTime(prevBPM.tick, bpmInfo.tick, resolution, prevBPM.value / 1000.0f);
                prevBPM = bpmInfo;
            }
        }

        time += TickFunctions.DisToTime(prevBPM.tick, position, resolution, prevBPM.value / 1000.0f);

        return((float)time);
    }
Exemple #5
0
    public void PreviewToggle()
    {
        _previewing = !_previewing;

        // Disable UI
        foreach (GameObject go in disableDuringPreview)
        {
            go.SetActive(!_previewing);
        }

        // Set chart view mode
        Globals.viewMode = Globals.ViewMode.Chart;

        if (_previewing)
        {
            // Record the current position
            initialPosition = editor.visibleStrikeline.position.y;

            // Move to the start of the chart
            editor.movement.SetTime(-3);

            // Play
            editor.Play();
        }
        else
        {
            // Stop
            editor.Stop();

            // Restore to initial position
            editor.movement.SetTime(TickFunctions.WorldYPositionToTime(initialPosition));
        }
    }
    void Update()
    {
        if (Input.GetMouseButtonDown(2))
        {
            middleClickDownScreenPos = Input.mousePosition;
        }
        else if (!Input.GetMouseButton(2) && middleClickDownScreenPos.HasValue)
        {
            middleClickDownScreenPos = null;
            Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto);
        }

        if (Input.GetMouseButtonUp(0) && editor.currentState == ChartEditor.State.Editor)
        {
            cancel = false;
        }

        if (Services.IsInDropDown)
        {
            cancel = true;
        }

        // Update timer text
        if (timePosition)
        {
            bool audioLoaded = false;
            foreach (var stream in editor.currentSongAudio.bassAudioStreams)
            {
                if (AudioManager.StreamIsValid(stream))
                {
                    audioLoaded = true;
                }
            }

            if (!audioLoaded)//editor.currentSong.songAudioLoaded)
            {
                timePosition.color = Color.red;
                timePosition.text  = "No audio";
            }
            else
            {
                timePosition.color = Color.white;
                timePosition.text  = Utility.timeConvertion(TickFunctions.WorldYPositionToTime(strikeLine.position.y));
            }
        }

        if (MSChartEditorInput.GetGroupInputDown(arrowKeyShortcutGroup))
        {
            arrowMoveTimer = 0;
        }
        else if (MSChartEditorInput.GetGroupInput(arrowKeyShortcutGroup))
        {
            arrowMoveTimer += Time.deltaTime;
        }
        else
        {
            arrowMoveTimer = 0;
        }
    }
Exemple #7
0
 public void SetTime(float time)
 {
     //if (ChartEditor.Instance.currentState == ChartEditor.State.Editor)
     {
         Vector3 pos = initPos;
         pos.y += TickFunctions.TimeToWorldYPosition(time);
         transform.position = pos;
     }
 }
 public void SetTime(float time)
 {
     if (Globals.applicationMode == Globals.ApplicationMode.Editor)
     {
         Vector3 pos = initPos;
         pos.y += TickFunctions.TimeToWorldYPosition(time);
         transform.position = pos;
     }
 }
Exemple #9
0
    public void PlayingMovement()
    {
        float   speed          = GameSettings.hyperspeed;
        Vector3 pos            = transform.position;
        float   deltaTime      = Time.deltaTime;
        float   positionOffset = initPos.y;

        {
            float timeBeforeMovement = TickFunctions.WorldYPositionToTime(pos.y - positionOffset);
            float timeAfterMovement  = timeBeforeMovement + deltaTime * GameSettings.gameSpeed;

            // Make sure we're staying in sync with the audio
            {
                SongAudioManager songAudioManager = editor.currentSongAudio;

                AudioStream stream = null;

                for (int i = 0; i < EnumX <Song.AudioInstrument> .Count; ++i)
                {
                    Song.AudioInstrument audio = (Song.AudioInstrument)i;
                    if (AudioManager.StreamIsValid(songAudioManager.GetAudioStream(audio)))
                    {
                        stream = songAudioManager.GetAudioStream(audio);
                        break;
                    }
                }

                if (AudioManager.StreamIsValid(stream) && stream.IsPlaying())
                {
                    float audioTimePosition = stream.CurrentPositionInSeconds() - editor.services.totalSongAudioOffset;
                    float desyncAmount      = audioTimePosition - timeAfterMovement;

                    if (Mathf.Abs(desyncAmount) > DESYNCLENIENCE)
                    {
                        timeAfterMovement += desyncAmount;
                    }
                }
            }

            float maxChangeInTimeAllowed = Application.targetFrameRate > 0 ? 2.0f / Application.targetFrameRate : 1.0f / 120.0f;

            float totalChangeInTime = timeAfterMovement - timeBeforeMovement;

            float newTimePosition = TickFunctions.TimeToWorldYPosition(timeBeforeMovement + totalChangeInTime);
            pos.y = newTimePosition + positionOffset;
        }

        selfTransform.position = pos;
        explicitChartPos       = null;

        lastUpdatedRealTime = Time.time;
    }
Exemple #10
0
    public void StartGameplay()
    {
        if (currentState == State.Playing ||
            movement.transform.position.y < movement.initPos.y ||
            Globals.ghLiveMode)
        {
            return;
        }

        float strikelineYPos = visibleStrikeline.position.y;
        float?stopResetTime  = null;

        songObjectPoolManager.noteVisibilityRangeYPosOverride = strikelineYPos;

        if (GameSettings.resetAfterGameplay)
        {
            stopResetTime = currentVisibleTime;
        }

        // Set position x seconds beforehand
        float startTime = TickFunctions.WorldYPositionToTime(strikelineYPos) - GameSettings.gameplayStartDelayTime - (0.01f * GameSettings.hyperspeed); // Offset to prevent errors where it removes a note that is on the strikeline

        movement.SetTime(startTime);

        GameSettings.bot = false;

        // Hide everything behind the strikeline
        foreach (Note note in currentChart.notes)
        {
            if (note.controller)
            {
                if (note.worldYPosition < strikelineYPos)
                {
                    note.controller.HideFullNote();
                }
                else
                {
                    break;
                }
            }
        }

        foreach (HitAnimation hitAnim in indicators.animations)
        {
            hitAnim.StopAnim();
        }

        SystemManagerState playingState = new PlayingState(startTime, stopResetTime);

        PopulatePersistentSystemsForNewState(State.Playing, playingState);
        ChangeState(State.Playing, playingState);
    }
    public override void OnSelectableMouseDrag()
    {
        // Move object
        if (bpm.tick != 0)
        {
            base.OnSelectableMouseDrag();
        }

        if (draggingInitialBpm != null && MSE.Input.KeyboardDevice.ctrlKeyBeingPressed && Input.GetMouseButton(1))
        {
            BPM previousBpm = SongObjectHelper.GetPreviousNonInclusive(bpm.song.bpms, bpm.tick);
            if (previousBpm != null && previousBpm.anchor == null)
            {
                float desiredWorldPos;
                if (editor.services.mouseMonitorSystem.world2DPosition != null && ((Vector2)editor.services.mouseMonitorSystem.world2DPosition).y < editor.mouseYMaxLimit.position.y)
                {
                    desiredWorldPos = ((Vector2)editor.services.mouseMonitorSystem.world2DPosition).y;
                }
                else
                {
                    desiredWorldPos = editor.mouseYMaxLimit.position.y;
                }

                float desiredTime = TickFunctions.WorldYPositionToTime(desiredWorldPos);
                if (desiredTime < previousBpm.time)
                {
                    desiredTime = previousBpm.time;
                }

                BPM nextBpm = SongObjectHelper.GetNextNonInclusive(bpm.song.bpms, bpm.tick);
                if (nextBpm != null && nextBpm.anchor != null && desiredTime >= nextBpm.time)
                {
                    desiredTime = nextBpm.time - 0.01f;
                }

                double disToBpm    = TickFunctions.DisToBpm(previousBpm.tick, bpm.tick, desiredTime - previousBpm.time, bpm.song.resolution);
                uint   newBpmValue = (uint)Mathf.Ceil((float)disToBpm * 1000.0f);
                if (newBpmValue > 0)
                {
                    if (hasPushed)
                    {
                        editor.commandStack.Pop();
                    }

                    editor.commandStack.Push(new SongEditModify <BPM>(previousBpm, new BPM(previousBpm.tick, newBpmValue, previousBpm.anchor)));
                    hasPushed = true;
                }
            }
        }
    }
Exemple #12
0
    void GenerateFixUpBPMAnchorCommands()
    {
        if (bpmAnchorFixup.Count > 0)
        {
            return;
        }

        Song song = ChartEditor.Instance.currentSong;
        var  bpms = song.bpms;

        tempAnchorFixupBPMs.Clear();
        tempAnchorFixupSynctrack.Clear();
        foreach (BPM bpm in bpms)
        {
            BPM clone = bpm.CloneAs <BPM>();
            tempAnchorFixupBPMs.Add(clone);
            tempAnchorFixupSynctrack.Add(clone);
        }

        // Fix up any anchors
        for (int i = 0; i < tempAnchorFixupBPMs.Count; ++i)
        {
            if (tempAnchorFixupBPMs[i].anchor != null && i > 0)
            {
                BPM anchorBPM   = tempAnchorFixupBPMs[i];
                BPM bpmToAdjust = tempAnchorFixupBPMs[i - 1];

                double deltaTime = (double)anchorBPM.anchor - Song.LiveTickToTime(bpmToAdjust.tick, song.resolution, tempAnchorFixupBPMs[0], tempAnchorFixupSynctrack);
                uint   newValue  = (uint)Mathf.Round((float)(TickFunctions.DisToBpm(bpmToAdjust.tick, anchorBPM.tick, deltaTime, song.resolution) * 1000.0d));

                if (deltaTime > 0 && newValue > 0)
                {
                    if (bpmToAdjust.value != newValue)
                    {
                        BPM original = bpmToAdjust.CloneAs <BPM>();
                        bpmToAdjust.value = newValue;

                        SongEditModify <BPM> command = new SongEditModify <BPM>(original, bpmToAdjust);
                        command.postExecuteEnabled = false;
                        bpmAnchorFixup.Add(command);
                    }
                }
            }
        }

        bpmAnchorFixupCommandsGenerated = true;
        tempAnchorFixupBPMs.Clear();
        tempAnchorFixupSynctrack.Clear();
    }
    void Update()
    {
        if (Input.GetMouseButtonUp(0) && Globals.applicationMode == Globals.ApplicationMode.Editor)
        {
            cancel = false;
        }

        if (Services.IsInDropDown)
        {
            cancel = true;
        }

        // Update timer text
        if (timePosition)
        {
            bool audioLoaded = false;
            foreach (var stream in editor.currentSong.bassAudioStreams)
            {
                if (AudioManager.StreamIsValid(stream))
                {
                    audioLoaded = true;
                }
            }

            if (!audioLoaded)//editor.currentSong.songAudioLoaded)
            {
                timePosition.color = Color.red;
                timePosition.text  = "No audio";
            }
            else
            {
                timePosition.color = Color.white;
                timePosition.text  = Utility.timeConvertion(TickFunctions.WorldYPositionToTime(strikeLine.position.y));
            }
        }

        if (Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.PageUp) || Input.GetKeyDown(KeyCode.PageDown))
        {
            arrowMoveTimer = 0;
        }
        else if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.PageUp) || Input.GetKey(KeyCode.PageDown))
        {
            arrowMoveTimer += Time.deltaTime;
        }
        else
        {
            arrowMoveTimer = 0;
        }
    }
Exemple #14
0
    public override void OnSelectableMouseDrag()
    {
        // Move object
        if (bpm.tick != 0)
        {
            base.OnSelectableMouseDrag();
        }

        if (draggingInitialBpm != null && ShortcutInput.modifierInput && Input.GetMouseButton(1))
        {
            BPM previousBpm = SongObjectHelper.GetPreviousNonInclusive(bpm.song.bpms, bpm.tick);
            if (previousBpm != null && previousBpm.anchor == null)
            {
                float desiredWorldPos;
                if (Mouse.world2DPosition != null && ((Vector2)Mouse.world2DPosition).y < editor.mouseYMaxLimit.position.y)
                {
                    desiredWorldPos = ((Vector2)Mouse.world2DPosition).y;
                }
                else
                {
                    desiredWorldPos = editor.mouseYMaxLimit.position.y;
                }

                float desiredTime = TickFunctions.WorldYPositionToTime(desiredWorldPos);
                if (desiredTime < previousBpm.time)
                {
                    desiredTime = previousBpm.time;
                }

                BPM nextBpm = SongObjectHelper.GetNextNonInclusive(bpm.song.bpms, bpm.tick);
                if (nextBpm != null && nextBpm.anchor != null && desiredTime >= nextBpm.time)
                {
                    desiredTime = nextBpm.time - 0.01f;
                }

                uint newBpmValue = (uint)(Mathf.Ceil((float)TickFunctions.DisToBpm(previousBpm.tick, bpm.tick, desiredTime - previousBpm.time, bpm.song.resolution)) * 1000);
                if (newBpmValue > 0)
                {
                    previousBpm.value = newBpmValue;
                }

                editor.songObjectPoolManager.SetAllPoolsDirty();
                ChartEditor.isDirty = true;
                editor.currentSong.UpdateCache();
                editor.FixUpBPMAnchors();
            }
        }
    }
Exemple #15
0
    /// <summary>
    /// Converts a tick position into the time it will appear in the song.
    /// </summary>
    /// <param name="position">Tick position.</param>
    /// <param name="resolution">Ticks per beat, usually provided from the resolution song of a Song class.</param>
    /// <returns>Returns the time in seconds.</returns>
    public float TickToTime(uint position, float resolution)
    {
        int previousBPMPos = SongObjectHelper.FindClosestPosition(position, bpms);

        if (bpms[previousBPMPos].tick > position)
        {
            --previousBPMPos;
        }

        BPM   prevBPM = bpms[previousBPMPos];
        float time    = prevBPM.assignedTime;

        time += (float)TickFunctions.DisToTime(prevBPM.tick, position, resolution, prevBPM.value / 1000.0f);

        return(time);
    }
Exemple #16
0
    void UpdateWaveformPointsFullData()
    {
        if (currentSample.data.Length <= 0 || currentSample == null)
        {
            return;
        }

        float     sampleRate = currentSample.length / currentSample.data.Length; // currentClip.samples / currentClip.length;
        float     scaling    = 1;
        const int iteration  = 1;                                                // 20;
        int       channels   = 1;                                                // currentSample.channels;
        float     fullOffset = -editor.currentSong.offset;

        // Determine what points of data to draw
        int startPos = timeToArrayPos(TickFunctions.WorldYPositionToTime(editor.camYMin.position.y) - fullOffset, iteration, channels, currentSample.length);
        int endPos   = timeToArrayPos(TickFunctions.WorldYPositionToTime(editor.camYMax.position.y) - fullOffset, iteration, channels, currentSample.length);

        Vector3[] points = new Vector3[endPos - startPos];
#if false
        if (currentSample.clip > 0)
        {
            scaling = (MAX_SCALE / currentSample.clip);
        }
#endif

        // Turn data into world-position points to feed the line renderer
        Vector3 point             = Vector3.zero;
        float[] currentSampleData = currentSample.data;
        float   hs = GameSettings.hyperspeed / GameSettings.gameSpeed;

        for (int i = startPos; i < endPos; ++i)
        {
            point.x = currentSampleData[i] * scaling;

            // Manual inlining of Song.TimeToWorldYPosition
            float time = i * sampleRate + fullOffset;
            point.y = time * hs;

            points[i - startPos] = point;
        }

        lineRen.numPositions = points.Length;
        lineRen.SetPositions(points);
    }
Exemple #17
0
    public void StartGameplay()
    {
        if (Globals.applicationMode == Globals.ApplicationMode.Playing ||
            movement.transform.position.y < movement.initPos.y ||
            Globals.ghLiveMode)
        {
            return;
        }

        if (GameSettings.resetAfterGameplay)
        {
            stopResetPos = movement.transform.position;
        }

        float strikelineYPos = visibleStrikeline.position.y - (0.01f * GameSettings.hyperspeed);     // Offset to prevent errors where it removes a note that is on the strikeline

        startGameplayPos = strikelineYPos;

        // Hide everything behind the strikeline
        foreach (Note note in currentChart.notes)
        {
            if (note.controller)
            {
                if (note.worldYPosition < strikelineYPos)
                {
                    note.controller.HideFullNote();
                }
                else
                {
                    break;
                }
            }
        }

        // Set position x seconds beforehand
        float time = TickFunctions.WorldYPositionToTime(strikelineYPos);

        movement.SetTime(time - GameSettings.gameplayStartDelayTime);

        GameSettings.bot = false;
        Play();
    }
    void UpdatePosBasedTimelineHandle()
    {
        if (editor.currentChart != null)
        {
            float endYPos       = TickFunctions.TimeToWorldYPosition(editor.currentSong.length);
            float totalDistance = endYPos - initPos.y - strikeLine.localPosition.y;

            if (totalDistance > 0)
            {
                float currentDistance = timeline.handlePos * totalDistance;

                transform.position = initPos + new Vector3(0, currentDistance, 0);
            }
            else
            {
                timeline.handlePos = 0;
                transform.position = initPos;
            }
        }
    }
Exemple #19
0
    void ManageGameplay()
    {
        Vector3 notePosition       = transform.position;
        Vector3 strikelinePosition = editor.visibleStrikeline.position;

        bool belowClapLine   = notePosition.y <= strikelinePosition.y + (TickFunctions.TimeToWorldYPosition(GameSettings.audioCalibrationMS / 1000.0f) * GameSettings.gameSpeed);
        bool belowStrikeLine = notePosition.y <= strikelinePosition.y + (Time.deltaTime * GameSettings.hyperspeed / GameSettings.gameSpeed);

        if (GameSettings.bot && belowClapLine)
        {
            GameplayBotHitClap();
        }

        if (hit && belowStrikeLine)
        {
            if (isActivated)
            {
                if (GameSettings.bot)
                {
                    PlayIndicatorAnim();
                }
                DeactivateNote();
            }

            // Resize sustain
            if (!sustainBroken && note.length > 0)
            {
                GameplaySustainHold();
            }
        }

        if (sustainBroken)
        {
            sustainRen.enabled = false;
        }

        if (whammy)
        {
            whammy.canWhammy = hit && !sustainBroken && !GameSettings.bot;
        }
    }
Exemple #20
0
    // Update is called once per frame
    public override void OnServiceUpdate()
    {
        // Offset by audio calibration
        Vector3 pos = initLocalPos;

#if BASS_AUDIO
        pos.y += TickFunctions.TimeToWorldYPosition(GameSettings.audioCalibrationMS / 1000.0f * GameSettings.gameSpeed);
#else
        pos.y += Song.TimeToWorldYPosition(Globals.clapCalibrationMS / 1000.0f * Globals.gameSpeed);
#endif
        transform.localPosition = pos;

        uint currentTickPos = editor.currentSong.WorldYPositionToTick(transform.position.y);

        if (Globals.applicationMode == Globals.ApplicationMode.Playing)
        {
            if (currentTickPos >= nextClapPos)
            {
                if (GameSettings.metronomeActive)
                {
#if BASS_AUDIO
                    int channel = Bass.BASS_SampleGetChannel(sample, false); // get a sample channel
                    if (channel != 0)
                    {
                        Bass.BASS_ChannelSetAttribute(channel, BASSAttribute.BASS_ATTRIB_VOL, GameSettings.sfxVolume * GameSettings.vol_master);
                        Bass.BASS_ChannelSetAttribute(channel, BASSAttribute.BASS_ATTRIB_PAN, GameSettings.audio_pan);
                        Bass.BASS_ChannelPlay(channel, false); // play it
                    }
                    else
                    {
                        Debug.LogError("Clap error: " + Bass.BASS_ErrorGetCode() + ", " + sample);
                    }
#else
                    clapSource.PlayOneShot(clap);
#endif
                }
            }
        }

        nextClapPos = CalculateNextBeatTickPosition(currentTickPos);
    }
    public void PlayingMovement()
    {
        float   speed     = GameSettings.hyperspeed;
        Vector3 pos       = transform.position;
        float   deltaTime = Time.deltaTime;

        //float oldPos = pos.y;

        if (playStartTime != null && playStartPosition != null)
        {
            float time = Time.realtimeSinceStartup - (float)playStartTime; //(float)timeSync.GetTime();//
            if (time < 0)
            {
                time = 0;
            }

            pos.y = (float)playStartPosition + TickFunctions.TimeToWorldYPosition(time * GameSettings.gameSpeed);

            //time -= (Globals.audioCalibrationMS / 1000f * Globals.gameSpeed + editor.currentSong.offset);

            //pos.y = /*(float)playStartPosition +*/ Song.TimeToWorldYPosition(time);
        }
        else
        {
            pos.y += (speed * deltaTime);
        }

        //float newPos = pos.y;

        //if ((newPos - oldPos) > 0.4)
        //Debug.Log("Position difference: " + (newPos - oldPos) + ", Delta time: " + Time.deltaTime + ", Frame: " + Time.frameCount);
        //Debug.Log(Time.renderedFrameCount);
        selfTransform.position = pos;
        explicitChartPos       = null;

        lastUpdatedRealTime = Time.time;
    }
    void UpdateTimelineHandleBasedPos()
    {
        if (editor.currentChart != null)
        {
            // Front cap
            if (Globals.applicationMode == Globals.ApplicationMode.Editor)
            {
                if (transform.position.y < initPos.y)
                {
                    transform.position = initPos;
                }
            }

            float endYPos       = TickFunctions.TimeToWorldYPosition(editor.currentSong.length);
            float totalDistance = endYPos - initPos.y - strikeLine.localPosition.y;

            if (transform.position.y + strikeLine.localPosition.y > endYPos)
            {
                transform.position = new Vector3(transform.position.x, endYPos - strikeLine.localPosition.y, transform.position.z);
            }

            float currentDistance = transform.position.y - initPos.y;

            //if (Globals.applicationMode != Globals.ApplicationMode.Playing)
            //{
            if (totalDistance > 0)
            {
                timeline.handlePos = currentDistance / totalDistance;
            }
            else
            {
                timeline.handlePos = 0;
            }
            //}
        }
    }
Exemple #23
0
 public float TickToWorldYPosition(uint position, float resolution)
 {
     return(TickFunctions.TimeToWorldYPosition(TickToTime(position, resolution)));
 }
    static MoonscraperEngine.ICommand GenerateCommandsAdjustedForAnchors(BPM currentBPM, uint desiredBpmValue)
    {
        List <SongEditCommand> commands = new List <SongEditCommand>();

        int pos = SongObjectHelper.FindObjectPosition(currentBPM, currentBPM.song.bpms);

        if (pos != SongObjectHelper.NOTFOUND)
        {
            BPM anchor      = null;
            BPM bpmToAdjust = null;

            int anchorPos = 0;

            // Get the next anchor
            for (int i = pos + 1; i < currentBPM.song.bpms.Count; ++i)
            {
                if (currentBPM.song.bpms[i].anchor != null)
                {
                    anchor    = currentBPM.song.bpms[i];
                    anchorPos = i;
                    // Get the bpm before that anchor
                    bpmToAdjust = currentBPM.song.bpms[i - 1];

                    break;
                }
            }

            if (anchor == null || bpmToAdjust == currentBPM)
            {
                commands.Add(new SongEditModify <BPM>(currentBPM, new BPM(currentBPM.tick, desiredBpmValue, currentBPM.anchor)));
                return(new BatchedSongEditCommand(commands));
            }

            // Calculate the minimum the bpm can adjust to
            const float MIN_DT = 0.01f;

            float bpmTime    = (float)anchor.anchor - MIN_DT;
            float resolution = currentBPM.song.resolution;
            // Calculate the time of the 2nd bpm pretending that the adjustable one is super close to the anchor
            for (int i = anchorPos - 1; i > pos + 1; --i)
            {
                // Calculate up until 2 bpms before the anchor
                // Re-hash of the actual time calculation equation in Song.cs
                bpmTime -= (float)TickFunctions.DisToTime(currentBPM.song.bpms[i - 1].tick, currentBPM.song.bpms[i].tick, resolution, currentBPM.song.bpms[i - 1].value / 1000.0f);
            }

            float timeBetweenFirstAndSecond = bpmTime - currentBPM.time;
            // What bpm will result in this exact time difference?
            uint minVal = (uint)(Mathf.Ceil((float)TickFunctions.DisToBpm(currentBPM.song.bpms[pos].tick, currentBPM.song.bpms[pos + 1].tick, timeBetweenFirstAndSecond, currentBPM.song.resolution)) * 1000);

            if (desiredBpmValue < minVal)
            {
                desiredBpmValue = minVal;
            }

            BPM  anchorBPM = anchor;
            uint oldValue  = currentBPM.value;

            ChartEditor editor = ChartEditor.Instance;
            currentBPM.value = desiredBpmValue; // Very much cheating, better to not do this
            double deltaTime = (double)anchorBPM.anchor - editor.currentSong.LiveTickToTime(bpmToAdjust.tick, editor.currentSong.resolution);
            uint   newValue  = (uint)Mathf.Round((float)(TickFunctions.DisToBpm(bpmToAdjust.tick, anchorBPM.tick, deltaTime, editor.currentSong.resolution) * 1000.0d));
            currentBPM.value = oldValue;

            uint finalValue = oldValue;
            if (deltaTime > 0 && newValue > 0)
            {
                if (newValue != 0)
                {
                    commands.Add(new SongEditModify <BPM>(bpmToAdjust, new BPM(bpmToAdjust.tick, newValue, bpmToAdjust.anchor)));
                }

                finalValue = desiredBpmValue;
            }

            desiredBpmValue = finalValue;
        }

        if (desiredBpmValue == currentBPM.value)
        {
            return(null);
        }

        commands.Add(new SongEditModify <BPM>(currentBPM, new BPM(currentBPM.tick, desiredBpmValue, currentBPM.anchor)));
        return(new BatchedSongEditCommand(commands));
    }
    public IEnumerator _ExportSong(string filepath)
    {
        // Start saving
        Globals.applicationMode = Globals.ApplicationMode.Loading;
        loadingScreen.FadeIn();
        loadingScreen.loadingInformation.text = "Exporting " + exportOptions.format;

        Song song = new Song(editor.currentSong);

        exportOptions.tickOffset = TickFunctions.TimeToDis(0, delayTime, exportOptions.targetResolution, 120);

        float  timer            = Time.realtimeSinceStartup;
        string errorMessageList = string.Empty;
        Thread exportingThread  = new Thread(() =>
        {
            if (exportOptions.format == ExportOptions.Format.Chart)
            {
                try
                {
                    new ChartWriter(filepath).Write(song, exportOptions, out errorMessageList);
                    //song.Save(filepath, exportOptions);
                }
                catch (System.Exception e)
                {
                    Logger.LogException(e, "Error when exporting chart");
                    errorMessageList += e.Message;
                }
            }
            else if (exportOptions.format == ExportOptions.Format.Midi)
            {
                try
                {
                    MidWriter.WriteToFile(filepath, song, exportOptions);
                }
                catch (System.Exception e)
                {
                    Logger.LogException(e, "Error when exporting midi");
                    errorMessageList += e.Message;
                }
            }
        });

        exportingThread.Start();

        while (exportingThread.ThreadState == ThreadState.Running)
        {
            yield return(null);
        }

        if (generateIniToggle.isOn)
        {
            loadingScreen.loadingInformation.text = "Generating Song.ini";
            Thread iniThread = new Thread(() =>
            {
                GenerateSongIni(Path.GetDirectoryName(filepath));
            });

            iniThread.Start();

            while (iniThread.ThreadState == ThreadState.Running)
            {
                yield return(null);
            }
        }

        Debug.Log("Total exporting time: " + (Time.realtimeSinceStartup - timer));

        // Stop loading animation
        loadingScreen.FadeOut();
        loadingScreen.loadingInformation.text = "Complete!";

        if (errorMessageList != string.Empty)
        {
            ChartEditor.Instance.errorManager.QueueErrorMessage("Encountered the following errors while exporting: " + Globals.LINE_ENDING + errorMessageList);
        }
    }
    public IEnumerator _ExportSong(string filepath)
    {
        LoadingTasksManager tasksManager = editor.services.loadingTasksManager;

        Song song = editor.currentSong;// new Song(editor.currentSong);

        exportOptions.tickOffset = TickFunctions.TimeToDis(0, delayTime, exportOptions.targetResolution, 120);

        float  timer            = Time.realtimeSinceStartup;
        string errorMessageList = string.Empty;

        List <LoadingTask> tasks = new List <LoadingTask>()
        {
            new LoadingTask("Exporting " + exportOptions.format, () =>
            {
                if (exportOptions.format == ExportOptions.Format.Chart)
                {
                    try
                    {
                        new ChartWriter(filepath).Write(song, exportOptions, out errorMessageList);
                        //song.Save(filepath, exportOptions);
                    }
                    catch (System.Exception e)
                    {
                        Logger.LogException(e, "Error when exporting chart");
                        errorMessageList += e.Message;
                    }
                }
                else if (exportOptions.format == ExportOptions.Format.Midi)
                {
                    try
                    {
                        MidWriter.WriteToFile(filepath, song, exportOptions);
                    }
                    catch (System.Exception e)
                    {
                        Logger.LogException(e, "Error when exporting midi");
                        errorMessageList += e.Message;
                    }
                }
            })
        };

        if (generateIniToggle.isOn)
        {
            tasks.Add(new LoadingTask("Generating Song.ini", () =>
            {
                GenerateSongIni(Path.GetDirectoryName(filepath), song);
            }));
        }

        tasksManager.KickTasks(tasks);

        while (tasksManager.isRunningTask)
        {
            yield return(null);
        }

        Debug.Log("Total exporting time: " + (Time.realtimeSinceStartup - timer));

        if (errorMessageList != string.Empty)
        {
            ChartEditor.Instance.errorManager.QueueErrorMessage("Encountered the following errors while exporting: " + Globals.LINE_ENDING + errorMessageList);
        }
    }
Exemple #27
0
    bool AdjustForAnchors(uint newBpmValue)
    {
        ChartEditor.GetInstance().songObjectPoolManager.SetAllPoolsDirty();

        int pos = SongObjectHelper.FindObjectPosition(currentBPM, currentBPM.song.bpms);

        if (pos != SongObjectHelper.NOTFOUND)
        {
            BPM anchor      = null;
            BPM bpmToAdjust = null;

            int anchorPos = 0;

            // Get the next anchor
            for (int i = pos + 1; i < currentBPM.song.bpms.Count; ++i)
            {
                if (currentBPM.song.bpms[i].anchor != null)
                {
                    anchor    = currentBPM.song.bpms[i];
                    anchorPos = i;
                    // Get the bpm before that anchor
                    bpmToAdjust = currentBPM.song.bpms[i - 1];

                    break;
                }
            }

            if (anchor == null || bpmToAdjust == currentBPM)
            {
                if (currentBPM.value != newBpmValue)
                {
                    ChartEditor.isDirty = true;
                }

                currentBPM.value = newBpmValue;
                return(true);
            }

            // Calculate the minimum the bpm can adjust to
            const float MIN_DT = 0.01f;

            float bpmTime    = (float)anchor.anchor - MIN_DT;
            float resolution = currentBPM.song.resolution;
            // Calculate the time of the 2nd bpm pretending that the adjustable one is super close to the anchor
            for (int i = anchorPos - 1; i > pos + 1; --i)
            {
                // Calculate up until 2 bpms before the anchor
                // Re-hash of the actual time calculation equation in Song.cs
                bpmTime -= (float)TickFunctions.DisToTime(currentBPM.song.bpms[i - 1].tick, currentBPM.song.bpms[i].tick, resolution, currentBPM.song.bpms[i - 1].value / 1000.0f);
            }

            float timeBetweenFirstAndSecond = bpmTime - currentBPM.time;
            // What bpm will result in this exact time difference?
            uint minVal = (uint)(Mathf.Ceil((float)TickFunctions.DisToBpm(currentBPM.song.bpms[pos].tick, currentBPM.song.bpms[pos + 1].tick, timeBetweenFirstAndSecond, currentBPM.song.resolution)) * 1000);

            if (newBpmValue < minVal)
            {
                newBpmValue = minVal;
            }

            if (anchorAdjustment == null)
            {
                anchorAdjustment = bpmToAdjust;
                anchorAdjustmentOriginalValue = new BPM(bpmToAdjust);
            }

            BPM  anchorBPM = anchor;
            uint oldValue  = currentBPM.value;
            currentBPM.value = newBpmValue;

            double deltaTime = (double)anchorBPM.anchor - editor.currentSong.LiveTickToTime(bpmToAdjust.tick, editor.currentSong.resolution);
            uint   newValue  = (uint)Mathf.Round((float)(TickFunctions.DisToBpm(bpmToAdjust.tick, anchorBPM.tick, deltaTime, editor.currentSong.resolution) * 1000.0d));
            currentBPM.value = oldValue;
            if (deltaTime > 0 && newValue > 0)
            {
                if (newValue != 0)
                {
                    bpmToAdjust.value = newValue;
                }
                currentBPM.value = newBpmValue;

                ChartEditor.isDirty = true;
            }
        }
        else
        {
            if (currentBPM.value != newBpmValue)
            {
                ChartEditor.isDirty = true;
            }

            currentBPM.value = newBpmValue;
        }

        return(true);
    }
    public IEnumerator _ExportSong(string filepath)
    {
        LoadingTasksManager tasksManager = editor.services.loadingTasksManager;

        Song  song       = editor.currentSong;// new Song(editor.currentSong);
        float songLength = editor.currentSongLength;

        exportOptions.tickOffset = TickFunctions.TimeToDis(0, delayTime, exportOptions.targetResolution, 120);

        float  timer            = Time.realtimeSinceStartup;
        string errorMessageList = string.Empty;

        List <LoadingTask> tasks = new List <LoadingTask>()
        {
            new LoadingTask("Exporting " + exportOptions.format, () =>
            {
                if (exportOptions.format == ExportOptions.Format.Chart)
                {
                    try
                    {
                        ChartWriter.ErrorReport errorReport;

                        Debug.Log("Exporting CHART file to " + filepath);
                        new ChartWriter(filepath).Write(song, exportOptions, out errorReport);

                        errorMessageList = errorReport.errorList.ToString();
                    }
                    catch (System.Exception e)
                    {
                        Logger.LogException(e, "Error when exporting chart");
                        errorMessageList += e.Message;
                    }
                }
                else if (exportOptions.format == ExportOptions.Format.Midi)
                {
                    try
                    {
                        Debug.Log("Exporting MIDI file to " + filepath);
                        MidWriter.WriteToFile(filepath, song, exportOptions);
                    }
                    catch (System.Exception e)
                    {
                        Logger.LogException(e, "Error when exporting midi");
                        errorMessageList += e.Message;
                    }
                }
            })
        };

        if (generateIniToggle.isOn)
        {
            tasks.Add(new LoadingTask("Generating Song.ini", () =>
            {
                GenerateSongIni(Path.GetDirectoryName(filepath), song, songLength);
            }));
        }

        tasksManager.KickTasks(tasks);

        while (tasksManager.isRunningTask)
        {
            yield return(null);
        }

        Debug.Log("Total exporting time: " + (Time.realtimeSinceStartup - timer));

        if (exportOptions.format == ExportOptions.Format.Midi)
        {
            bool hasErrors;
            SongValidate.ValidationParameters validateParams = new SongValidate.ValidationParameters()
            {
                songLength = editor.currentSongLength, checkMidiIssues = true,
            };
            string validationErrors = SongValidate.GenerateReport(SongValidate.ValidationOptions.CloneHero, editor.currentSong, validateParams, out hasErrors);

            if (hasErrors)
            {
                errorMessageList += '\n';
                errorMessageList += validationErrors;
            }
        }

        if (errorMessageList != string.Empty)
        {
            Disable();
            ChartEditor.Instance.errorManager.QueueErrorMessage("Encountered the following errors while exporting: " + Globals.LINE_ENDING + errorMessageList);
        }
    }
Exemple #29
0
 public uint WorldYPositionToTick(float worldYPos, float resolution)
 {
     return(TimeToTick(TickFunctions.WorldYPositionToTime(worldYPos), resolution));
 }
Exemple #30
0
    // Paste the clipboard data into the chart, overwriting anything else in the process
    public void Paste(uint chartLocationToPaste)
    {
        //if (System.Windows.Forms.Clipboard.GetDataObject().GetFormats().Length > 0 &&
        //    !(
        //        System.Windows.Forms.Clipboard.ContainsText(TextDataFormat.UnicodeText) &&
        //        System.Windows.Forms.Clipboard.ContainsText(TextDataFormat.Text) &&
        //        System.Windows.Forms.Clipboard.GetText() == "")
        //    )     // Something else is pasted on the clipboard instead of Moonscraper stuff.
        //    return;

        FileStream fs = null;

        clipboard = null;
        try
        {
            // Read clipboard data from a file instead of the actual clipboard because the actual clipboard doesn't work for whatever reason
            fs = new FileStream(CLIPBOARD_FILE_LOCATION, FileMode.Open);
            BinaryFormatter formatter = new BinaryFormatter();

            clipboard = (Clipboard)formatter.Deserialize(fs);
        }
        catch (System.Exception e)
        {
            Logger.LogException(e, "Failed to read from clipboard file");
            clipboard = null;
        }
        finally
        {
            if (fs != null)
            {
                fs.Close();
            }
            else
            {
                Debug.LogError("Filestream when reading clipboard data failed to initialise");
            }
        }

        if (Globals.applicationMode == Globals.ApplicationMode.Editor && clipboard != null && clipboard.data.Length > 0)
        {
            List <SongEditCommand> commands = new List <SongEditCommand>();

            Rect collisionRect = clipboard.GetCollisionRect(chartLocationToPaste, editor.currentSong);
            if (clipboard.areaChartPosMin > clipboard.areaChartPosMax)
            {
                Debug.LogError("Clipboard minimum (" + clipboard.areaChartPosMin + ") is greater than clipboard the max (" + clipboard.areaChartPosMax + ")");
            }
            uint colliderChartDistance = TickFunctions.TickScaling(clipboard.areaChartPosMax - clipboard.areaChartPosMin, clipboard.resolution, editor.currentSong.resolution);

            viewModeController.ToggleSongViewMode(!clipboard.data[0].GetType().IsSubclassOf(typeof(ChartObject)));

            {
                List <SongObject> newObjectsToDelete = new List <SongObject>();

                // Overwrite any objects in the clipboard space
                if (clipboard.data[0].GetType().IsSubclassOf(typeof(ChartObject)))
                {
                    foreach (ChartObject chartObject in editor.currentChart.chartObjects)
                    {
                        if (chartObject.tick >= chartLocationToPaste && chartObject.tick <= (chartLocationToPaste + colliderChartDistance) && PrefabGlobals.HorizontalCollisionCheck(PrefabGlobals.GetCollisionRect(chartObject), collisionRect))
                        {
                            newObjectsToDelete.Add(chartObject);
                        }
                    }
                }
                else
                {
                    // Overwrite synctrack, leave sections alone
                    foreach (SyncTrack syncObject in editor.currentSong.syncTrack)
                    {
                        if (syncObject.tick >= chartLocationToPaste && syncObject.tick <= (chartLocationToPaste + colliderChartDistance) && PrefabGlobals.HorizontalCollisionCheck(PrefabGlobals.GetCollisionRect(syncObject), collisionRect))
                        {
                            newObjectsToDelete.Add(syncObject);
                        }
                    }
                }

                if (newObjectsToDelete.Count > 0)
                {
                    commands.Add(new SongEditDelete(newObjectsToDelete));
                }
            }

            {
                uint maxLength = editor.currentSong.TimeToTick(editor.currentSong.length, editor.currentSong.resolution);

                List <SongObject> newObjectsToAddIn = new List <SongObject>();

                // Paste the new objects in
                foreach (SongObject clipboardSongObject in clipboard.data)
                {
                    SongObject objectToAdd = clipboardSongObject.Clone();

                    objectToAdd.tick = chartLocationToPaste +
                                       TickFunctions.TickScaling(clipboardSongObject.tick, clipboard.resolution, editor.currentSong.resolution) -
                                       TickFunctions.TickScaling(clipboard.areaChartPosMin, clipboard.resolution, editor.currentSong.resolution);

                    if (objectToAdd.tick >= maxLength)
                    {
                        break;
                    }

                    if (objectToAdd.GetType() == typeof(Note))
                    {
                        Note note = (Note)objectToAdd;

                        if (clipboard.instrument == Song.Instrument.GHLiveGuitar || clipboard.instrument == Song.Instrument.GHLiveBass)
                        {
                            // Pasting from a ghl track
                            if (!Globals.ghLiveMode)
                            {
                                if (note.ghliveGuitarFret == Note.GHLiveGuitarFret.Open)
                                {
                                    note.guitarFret = Note.GuitarFret.Open;
                                }
                                else if (note.ghliveGuitarFret == Note.GHLiveGuitarFret.White3)
                                {
                                    continue;
                                }
                            }
                        }
                        else if (Globals.ghLiveMode)
                        {
                            // Pasting onto a ghl track
                            if (note.guitarFret == Note.GuitarFret.Open)
                            {
                                note.ghliveGuitarFret = Note.GHLiveGuitarFret.Open;
                            }
                        }

                        note.length = TickFunctions.TickScaling(note.length, clipboard.resolution, editor.currentSong.resolution);
                    }
                    else if (objectToAdd.GetType() == typeof(Starpower))
                    {
                        Starpower sp = (Starpower)objectToAdd;
                        sp.length = TickFunctions.TickScaling(sp.length, clipboard.resolution, editor.currentSong.resolution);
                    }

                    newObjectsToAddIn.Add(objectToAdd);
                }

                if (newObjectsToAddIn.Count > 0)
                {
                    commands.Add(new SongEditAdd(newObjectsToAddIn));
                }
            }

            if (commands.Count > 0)
            {
                BatchedSongEditCommand batchedCommands = new BatchedSongEditCommand(commands);
                editor.commandStack.Push(batchedCommands);
            }
        }
        // 0 objects in clipboard, don't bother pasting
    }