/// <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); }
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); }
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); }
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; } }
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; } }
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; }
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; } } } }
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; } }
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(); } } }
/// <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); }
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); }
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; } } }
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; } }
// 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; } //} } }
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); } }
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); } }
public uint WorldYPositionToTick(float worldYPos, float resolution) { return(TimeToTick(TickFunctions.WorldYPositionToTime(worldYPos), resolution)); }
// 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 }