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 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(); }
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(); } } }
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); }
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)); }