diff --git a/assets b/assets index f3e9cd835..830127dcc 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f3e9cd8355f20445fcad7030fdb6363a2325adb3 +Subproject commit 830127dcc38e4f0fc35b162bd0f696a77679b046 diff --git a/source/funkin/data/song/SongDataUtils.hx b/source/funkin/data/song/SongDataUtils.hx index 9a9f758b1..4ae4b1426 100644 --- a/source/funkin/data/song/SongDataUtils.hx +++ b/source/funkin/data/song/SongDataUtils.hx @@ -32,10 +32,7 @@ class SongDataUtils return new SongNoteData(time, data, length, kind); }; - trace(notes); - trace(notes[0]); var result = [for (i in 0...notes.length) offsetNote(notes[i])]; - trace(result); return result; } @@ -54,6 +51,36 @@ class SongDataUtils }); } + /** + * Given an array of SongNoteData objects, return a new array of SongNoteData objects + * which excludes any notes whose timestamps are outside of the given range. + * @param notes The notes to modify. + * @param startTime The start of the range in milliseconds. + * @param endTime The end of the range in milliseconds. + * @return The filtered array of notes. + */ + public static function clampSongNoteData(notes:Array, startTime:Float, endTime:Float):Array + { + return notes.filter(function(note:SongNoteData):Bool { + return note.time >= startTime && note.time <= endTime; + }); + } + + /** + * Given an array of SongEventData objects, return a new array of SongEventData objects + * which excludes any events whose timestamps are outside of the given range. + * @param events The events to modify. + * @param startTime The start of the range in milliseconds. + * @param endTime The end of the range in milliseconds. + * @return The filtered array of events. + */ + public static function clampSongEventData(events:Array, startTime:Float, endTime:Float):Array + { + return events.filter(function(event:SongEventData):Bool { + return event.time >= startTime && event.time <= endTime; + }); + } + /** * Return a new array without a certain subset of notes from an array of SongNoteData objects. * Does not mutate the original array. diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index bd4b0f5e1..bf6df4423 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -477,6 +477,8 @@ class PlayState extends MusicBeatSubState var generatedMusic:Bool = false; var perfectMode:Bool = false; + static final BACKGROUND_COLOR:FlxColor = FlxColor.MAGENTA; + /** * Instantiate a new PlayState. * @param params The parameters used to initialize the PlayState. @@ -641,6 +643,24 @@ class PlayState extends MusicBeatSubState initialized = true; } + public override function draw():Void + { + // if (FlxG.renderBlit) + // { + // camGame.fill(BACKGROUND_COLOR); + // } + // else if (FlxG.renderTile) + // { + // FlxG.log.warn("PlayState background not displayed properly on tile renderer!"); + // } + // else + // { + // FlxG.log.warn("PlayState background not displayed properly, unknown renderer!"); + // } + + super.draw(); + } + function assertChartExists():Bool { // Returns null if the song failed to load or doesn't have the selected difficulty. @@ -1272,6 +1292,7 @@ class PlayState extends MusicBeatSubState function initCameras():Void { camGame = new SwagCamera(); + camGame.bgColor = BACKGROUND_COLOR; // Show a pink background behind the stage. camHUD = new FlxCamera(); camHUD.bgColor.alpha = 0; // Show the game scene behind the camera. camCutscene = new FlxCamera(); diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 519d1a54a..a3a8344c8 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2223,11 +2223,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState #if sys menubarItemGoToBackupsFolder.onClick = _ -> this.openBackupsFolder(); #else - // Disable the menu item if we're not on a desktop platform. var menubarItemGoToBackupsFolder = findComponent('menubarItemGoToBackupsFolder', MenuItem); if (menubarItemGoToBackupsFolder != null) menubarItemGoToBackupsFolder.disabled = true; - #end menubarItemUserGuide.onClick = _ -> this.openUserGuideDialog(); @@ -4345,7 +4343,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var startTimestamp:Float = 0; if (playtestStartTime) startTimestamp = scrollPositionInMs + playheadPositionInMs; - var targetSong:Song = Song.buildRaw(currentSongId, songMetadata.values(), availableVariations, songChartData, false); + var targetSong:Song; + try + { + targetSong = Song.buildRaw(currentSongId, songMetadata.values(), availableVariations, songChartData, false); + } + catch (e) + { + this.error("Could Not Playtest", 'Got an error trying to playtest the song.\n${e}'); + return; + } // TODO: Rework asset system so we can remove this. switch (currentSongStage) @@ -4389,6 +4396,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Override music. if (audioInstTrack != null) FlxG.sound.music = audioInstTrack; if (audioVocalTrackGroup != null) targetState.vocals = audioVocalTrackGroup; + + this.persistentUpdate = false; + this.persistentDraw = false; stopWelcomeMusic(); openSubState(targetState); } @@ -4603,6 +4613,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var prevDifficulty = availableDifficulties[availableDifficulties.length - 1]; selectedDifficulty = prevDifficulty; + Conductor.mapTimeChanges(this.currentSongMetadata.timeChanges); + refreshDifficultyTreeSelection(); refreshMetadataToolbox(); } @@ -4721,6 +4733,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState @:nullSafety(Off) function resetConductorAfterTest(_:FlxSubState = null):Void { + this.persistentUpdate = true; + this.persistentDraw = true; + moveSongToScrollPosition(); // Reapply the volume. diff --git a/source/funkin/ui/debug/charting/commands/ChangeStartingBPMCommand.hx b/source/funkin/ui/debug/charting/commands/ChangeStartingBPMCommand.hx new file mode 100644 index 000000000..3c45c1168 --- /dev/null +++ b/source/funkin/ui/debug/charting/commands/ChangeStartingBPMCommand.hx @@ -0,0 +1,61 @@ +package funkin.ui.debug.charting.commands; + +import funkin.data.song.SongData.SongTimeChange; + +/** + * A command which changes the starting BPM of the song. + */ +@:nullSafety +@:access(funkin.ui.debug.charting.ChartEditorState) +class ChangeStartingBPMCommand implements ChartEditorCommand +{ + var targetBPM:Float; + + var previousBPM:Float = 100; + + public function new(targetBPM:Float) + { + this.targetBPM = targetBPM; + } + + public function execute(state:ChartEditorState):Void + { + var timeChanges:Array = state.currentSongMetadata.timeChanges; + if (timeChanges == null || timeChanges.length == 0) + { + previousBPM = 100; + timeChanges = [new SongTimeChange(0, targetBPM)]; + } + else + { + previousBPM = timeChanges[0].bpm; + timeChanges[0].bpm = targetBPM; + } + + state.currentSongMetadata.timeChanges = timeChanges; + + Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges); + } + + public function undo(state:ChartEditorState):Void + { + var timeChanges:Array = state.currentSongMetadata.timeChanges; + if (timeChanges == null || timeChanges.length == 0) + { + timeChanges = [new SongTimeChange(0, previousBPM)]; + } + else + { + timeChanges[0].bpm = previousBPM; + } + + state.currentSongMetadata.timeChanges = timeChanges; + + Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges); + } + + public function toString():String + { + return 'Change Starting BPM to ${targetBPM}'; + } +} diff --git a/source/funkin/ui/debug/charting/commands/PasteItemsCommand.hx b/source/funkin/ui/debug/charting/commands/PasteItemsCommand.hx index 1857b44db..75382da41 100644 --- a/source/funkin/ui/debug/charting/commands/PasteItemsCommand.hx +++ b/source/funkin/ui/debug/charting/commands/PasteItemsCommand.hx @@ -32,10 +32,14 @@ class PasteItemsCommand implements ChartEditorCommand return; } - trace(currentClipboard.notes); + var stepEndOfSong:Float = Conductor.getTimeInSteps(state.songLengthInMs); + var stepCutoff:Float = stepEndOfSong - 1.0; + var msCutoff:Float = Conductor.getStepTimeInMs(stepCutoff); addedNotes = SongDataUtils.offsetSongNoteData(currentClipboard.notes, Std.int(targetTimestamp)); + addedNotes = SongDataUtils.clampSongNoteData(addedNotes, 0.0, msCutoff); addedEvents = SongDataUtils.offsetSongEventData(currentClipboard.events, Std.int(targetTimestamp)); + addedEvents = SongDataUtils.clampSongEventData(addedEvents, 0.0, msCutoff); state.currentSongChartNoteData = state.currentSongChartNoteData.concat(addedNotes); state.currentSongChartEventData = state.currentSongChartEventData.concat(addedEvents); diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx index 79937ce6f..0e7ba374c 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx @@ -110,12 +110,12 @@ class ChartEditorDialogHandler { var dialog:Null = openDialog(state, CHART_EDITOR_DIALOG_BACKUP_AVAILABLE_LAYOUT, true, true); if (dialog == null) throw 'Could not locate Backup Available dialog'; - dialog.onDialogClosed = function(_event) { + dialog.onDialogClosed = function(event) { state.isHaxeUIDialogOpen = false; - if (_event.button == DialogButton.APPLY) + if (event.button == DialogButton.APPLY) { // User loaded the backup! Close the welcome dialog behind this. - if (welcomeDialog != null) welcomeDialog.hideDialog(DialogButton.CANCEL); + if (welcomeDialog != null) welcomeDialog.hideDialog(DialogButton.APPLY); } else { @@ -137,22 +137,22 @@ class ChartEditorDialogHandler var buttonCancel:Null