diff --git a/Project.xml b/Project.xml index ccf6c83a3..69400d8b1 100644 --- a/Project.xml +++ b/Project.xml @@ -156,7 +156,6 @@ - @@ -196,6 +195,22 @@ + +
+ + +
+ +
+ + + + +
+ --> --> diff --git a/assets b/assets index d2b3dcab9..8104d43e5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d2b3dcab92f5cb4b11774a80cbe2e270972a9577 +Subproject commit 8104d43e584a1f25e574438d7b21a7e671358969 diff --git a/source/funkin/FreeplayState.hx b/source/funkin/FreeplayState.hx index a86ec0eaf..4e7674e93 100644 --- a/source/funkin/FreeplayState.hx +++ b/source/funkin/FreeplayState.hx @@ -533,7 +533,7 @@ class FreeplayState extends MusicBeatSubState var randomCapsule:SongMenuItem = grpCapsules.recycle(SongMenuItem); randomCapsule.init(FlxG.width, 0, "Random"); randomCapsule.onConfirm = function() { - trace("RANDOM SELECTED"); + capsuleOnConfirmRandom(randomCapsule); }; randomCapsule.y = randomCapsule.intendedY(0) + 10; randomCapsule.targetPos.x = randomCapsule.x; @@ -595,6 +595,8 @@ class FreeplayState extends MusicBeatSubState var spamTimer:Float = 0; var spamming:Bool = false; + var busy:Bool = false; // Set to true once the user has pressed enter to select a song. + override function update(elapsed:Float) { super.update(elapsed); @@ -646,6 +648,13 @@ class FreeplayState extends MusicBeatSubState txtCompletion.text = Math.floor(lerpCompletion * 100) + "%"; + handleInputs(elapsed); + } + + function handleInputs(elapsed:Float):Void + { + if (busy) return; + var upP = controls.UI_UP_P; var downP = controls.UI_DOWN_P; var accepted = controls.ACCEPT; @@ -908,8 +917,17 @@ class FreeplayState extends MusicBeatSubState } } + function capsuleOnConfirmRandom(cap:SongMenuItem):Void + { + trace("RANDOM SELECTED"); + + busy = true; + } + function capsuleOnConfirmDefault(cap:SongMenuItem):Void { + busy = true; + PlayStatePlaylist.isStoryMode = false; var songId:String = cap.songTitle.toLowerCase(); diff --git a/source/funkin/PauseSubState.hx b/source/funkin/PauseSubState.hx index f93e5a450..54c3a530b 100644 --- a/source/funkin/PauseSubState.hx +++ b/source/funkin/PauseSubState.hx @@ -150,6 +150,11 @@ class PauseSubState extends MusicBeatSubState super.update(elapsed); + handleInputs(); + } + + function handleInputs():Void + { var upP = controls.UI_UP_P; var downP = controls.UI_DOWN_P; var accepted = controls.ACCEPT; @@ -229,9 +234,14 @@ class PauseSubState extends MusicBeatSubState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - if (PlayStatePlaylist.isStoryMode) openSubState(new funkin.ui.StickerSubState(null, STORY)); + if (PlayStatePlaylist.isStoryMode) + { + openSubState(new funkin.ui.StickerSubState(null, STORY)); + } else + { openSubState(new funkin.ui.StickerSubState(null, FREEPLAY)); + } case 'Exit to Chart Editor': this.close(); diff --git a/source/funkin/ui/StickerSubState.hx b/source/funkin/ui/StickerSubState.hx index 067f50c31..ebf75cb34 100644 --- a/source/funkin/ui/StickerSubState.hx +++ b/source/funkin/ui/StickerSubState.hx @@ -17,6 +17,9 @@ import openfl.geom.Matrix; import openfl.display.Sprite; import openfl.display.Bitmap; +using Lambda; +using StringTools; + class StickerSubState extends MusicBeatSubState { public var grpStickers:FlxTypedGroup; @@ -26,10 +29,60 @@ class StickerSubState extends MusicBeatSubState var nextState:NEXTSTATE = FREEPLAY; + // what "folders" to potentially load from (as of writing only "keys" exist) + var soundSelections:Array = []; + // what "folder" was randomly selected + var soundSelection:String = ""; + var sounds:Array = []; + public function new(?oldStickers:Array, ?nextState:NEXTSTATE = FREEPLAY):Void { super(); + // todo still + // make sure that ONLY plays mp3/ogg files + // if there's no mp3/ogg file, then it regenerates/reloads the random folder + + var assetsInList = openfl.utils.Assets.list(); + + var soundFilterFunc = function(a:String) { + return a.startsWith('assets/shared/sounds/stickersounds/'); + }; + + soundSelections = assetsInList.filter(soundFilterFunc); + soundSelections = soundSelections.map(function(a:String) { + return a.replace('assets/shared/sounds/stickersounds/', '').split('/')[0]; + }); + + // cracked cleanup... yuchh... + for (i in soundSelections) + { + while (soundSelections.contains(i)) + { + soundSelections.remove(i); + } + soundSelections.push(i); + } + + trace(soundSelections); + + soundSelection = FlxG.random.getObject(soundSelections); + + var filterFunc = function(a:String) { + return a.startsWith('assets/shared/sounds/stickersounds/' + soundSelection + '/'); + }; + var assetsInList3 = openfl.utils.Assets.list(); + sounds = assetsInList3.filter(filterFunc); + for (i in 0...sounds.length) + { + sounds[i] = sounds[i].replace('assets/shared/sounds/', ''); + sounds[i] = sounds[i].substring(0, sounds[i].lastIndexOf('.')); + } + + trace(sounds); + + // trace(assetsInList); + this.nextState = nextState; grpStickers = new FlxTypedGroup(); @@ -66,6 +119,8 @@ class StickerSubState extends MusicBeatSubState { new FlxTimer().start(sticker.timing, _ -> { sticker.visible = false; + var daSound:String = FlxG.random.getObject(sounds); + FlxG.sound.play(Paths.sound(daSound)); if (ind == grpStickers.members.length - 1) { @@ -151,7 +206,11 @@ class StickerSubState extends MusicBeatSubState sticker.timing = FlxMath.remapToRange(ind, 0, grpStickers.members.length, 0, 0.9); new FlxTimer().start(sticker.timing, _ -> { + if (grpStickers == null) return; + sticker.visible = true; + var daSound:String = FlxG.random.getObject(sounds); + FlxG.sound.play(Paths.sound(daSound)); var frameTimer:Int = FlxG.random.int(0, 2); @@ -212,10 +271,10 @@ class StickerSubState extends MusicBeatSubState { super.update(elapsed); - if (FlxG.keys.justPressed.ANY) - { - regenStickers(); - } + // if (FlxG.keys.justPressed.ANY) + // { + // regenStickers(); + // } } var switchingState:Bool = false; diff --git a/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx b/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx index 9ac903e38..f116ad3f1 100644 --- a/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx +++ b/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx @@ -116,10 +116,10 @@ class ChartEditorImportExportHandler /** * @param force Whether to force the export without prompting the user for a file location. - * @param tmp If true, save to the temporary directory instead of the local `backup` directory. */ - public static function exportAllSongData(state:ChartEditorState, force:Bool = false, tmp:Bool = false):Void + public static function exportAllSongData(state:ChartEditorState, force:Bool = false):Void { + var tmp = false; var zipEntries:Array = []; for (variation in state.availableVariations) @@ -133,9 +133,9 @@ class ChartEditorImportExportHandler if (variationId == '') { var variationMetadata:Null = state.songMetadata.get(variation); - if (variationMetadata != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', SerializerUtil.toJSON(variationMetadata))); + if (variationMetadata != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', variationMetadata.serialize())); var variationChart:Null = state.songChartData.get(variation); - if (variationChart != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', SerializerUtil.toJSON(variationChart))); + if (variationChart != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', variationChart.serialize())); } else { diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index b94041afd..5e4dded91 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -695,6 +695,16 @@ class ChartEditorState extends HaxeUIState */ var downKeyHandler:TurboKeyHandler = TurboKeyHandler.build(FlxKey.DOWN); + /** + * Variable used to track how long the user has been holding the W keybind. + */ + var wKeyHandler:TurboKeyHandler = TurboKeyHandler.build(FlxKey.W); + + /** + * Variable used to track how long the user has been holding the S keybind. + */ + var sKeyHandler:TurboKeyHandler = TurboKeyHandler.build(FlxKey.S); + /** * Variable used to track how long the user has been holding the page-up keybind. */ @@ -1609,6 +1619,7 @@ class ChartEditorState extends HaxeUIState addUIClickListener('menubarItemSaveChartAs', _ -> ChartEditorImportExportHandler.exportAllSongData(this)); addUIClickListener('menubarItemLoadInst', _ -> ChartEditorDialogHandler.openUploadInstDialog(this, true)); addUIClickListener('menubarItemImportChart', _ -> ChartEditorDialogHandler.openImportChartDialog(this, 'legacy', true)); + addUIClickListener('menubarItemExit', _ -> quitChartEditor()); addUIClickListener('menubarItemUndo', _ -> undoLastCommand()); @@ -1663,16 +1674,20 @@ class ChartEditorState extends HaxeUIState addUIClickListener('menubarItemSelectNone', _ -> performCommand(new DeselectAllItemsCommand(currentNoteSelection, currentEventSelection))); - // TODO: Implement these. - // addUIClickListener('menubarItemSelectRegion', _ -> doSomething()); - // addUIClickListener('menubarItemSelectBeforeCursor', _ -> doSomething()); - // addUIClickListener('menubarItemSelectAfterCursor', _ -> doSomething()); - addUIClickListener('menubarItemPlaytestFull', _ -> testSongInPlayState(false)); addUIClickListener('menubarItemPlaytestMinimal', _ -> testSongInPlayState(true)); - addUIChangeListener('menubarItemInputStyleGroup', function(event:UIEvent) { - trace('Change input style: ${event.target}'); + addUIClickListener('menuBarItemNoteSnapDecrease', _ -> noteSnapQuantIndex--); + addUIClickListener('menuBarItemNoteSnapIncrease', _ -> noteSnapQuantIndex++); + + addUIChangeListener('menuBarItemInputStyleNone', function(event:UIEvent) { + currentLiveInputStyle = None; + }); + addUIChangeListener('menuBarItemInputStyleNumberKeys', function(event:UIEvent) { + currentLiveInputStyle = NumberKeys; + }); + addUIChangeListener('menuBarItemInputStyleWASD', function(event:UIEvent) { + currentLiveInputStyle = WASD; }); addUIClickListener('menubarItemAbout', _ -> ChartEditorDialogHandler.openAboutDialog(this)); @@ -1769,6 +1784,8 @@ class ChartEditorState extends HaxeUIState add(redoKeyHandler); add(upKeyHandler); add(downKeyHandler); + add(wKeyHandler); + add(sKeyHandler); add(pageUpKeyHandler); add(pageDownKeyHandler); } @@ -1795,7 +1812,7 @@ class ChartEditorState extends HaxeUIState // Auto-save to local storage. #else // Auto-save to temp file. - ChartEditorImportExportHandler.exportAllSongData(this, true, true); + ChartEditorImportExportHandler.exportAllSongData(this, true); #end } @@ -1817,6 +1834,13 @@ class ChartEditorState extends HaxeUIState public override function update(elapsed:Float):Void { + // Override F4 behavior to include the autosave. + if (FlxG.keys.justPressed.F4) + { + quitChartEditor(); + return; + } + // dispatchEvent gets called here. super.update(elapsed); @@ -1896,20 +1920,33 @@ class ChartEditorState extends HaxeUIState // Mouse Wheel = Scroll if (FlxG.mouse.wheel != 0 && !FlxG.keys.pressed.CONTROL) { - scrollAmount = -10 * FlxG.mouse.wheel; + scrollAmount = -50 * FlxG.mouse.wheel; shouldPause = true; } // Up Arrow = Scroll Up - if (upKeyHandler.activated && currentLiveInputStyle != LiveInputStyle.WASD) + if (upKeyHandler.activated && currentLiveInputStyle == None) { - scrollAmount = -GRID_SIZE * 0.25 * 5.0; + scrollAmount = -GRID_SIZE * 0.25 * 25.0; shouldPause = true; } // Down Arrow = Scroll Down - if (downKeyHandler.activated && currentLiveInputStyle != LiveInputStyle.WASD) + if (downKeyHandler.activated && currentLiveInputStyle == None) { - scrollAmount = GRID_SIZE * 0.25 * 5.0; + scrollAmount = GRID_SIZE * 0.25 * 25.0; + shouldPause = true; + } + + // W = Scroll Up (doesn't work with Ctrl+Scroll) + if (wKeyHandler.activated && currentLiveInputStyle == None && !FlxG.keys.pressed.CONTROL) + { + scrollAmount = -GRID_SIZE * 0.25 * 25.0; + shouldPause = true; + } + // S = Scroll Down (doesn't work with Ctrl+Scroll) + if (sKeyHandler.activated && currentLiveInputStyle == None && !FlxG.keys.pressed.CONTROL) + { + scrollAmount = GRID_SIZE * 0.25 * 25.0; shouldPause = true; } @@ -1974,7 +2011,7 @@ class ChartEditorState extends HaxeUIState // SHIFT + Scroll = Scroll Fast if (FlxG.keys.pressed.SHIFT) { - scrollAmount *= 5; + scrollAmount *= 2; } // CONTROL + Scroll = Scroll Precise if (FlxG.keys.pressed.CONTROL) @@ -2045,14 +2082,17 @@ class ChartEditorState extends HaxeUIState function handleSnap():Void { - if (FlxG.keys.justPressed.LEFT && !FlxG.keys.pressed.CONTROL) + if (currentLiveInputStyle == None) { - noteSnapQuantIndex--; - } + if (FlxG.keys.justPressed.LEFT && !FlxG.keys.pressed.CONTROL) + { + noteSnapQuantIndex--; + } - if (FlxG.keys.justPressed.RIGHT && !FlxG.keys.pressed.CONTROL) - { - noteSnapQuantIndex++; + if (FlxG.keys.justPressed.RIGHT && !FlxG.keys.pressed.CONTROL) + { + noteSnapQuantIndex++; + } } } @@ -3032,10 +3072,16 @@ class ChartEditorState extends HaxeUIState // CTRL + Q = Quit to Menu if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.Q) { - FlxG.switchState(new MainMenuState()); + quitChartEditor(); } } + function quitChartEditor():Void + { + autoSave(); + FlxG.switchState(new MainMenuState()); + } + /** * Handle keybinds for edit menu items. */ @@ -3124,13 +3170,17 @@ class ChartEditorState extends HaxeUIState */ function handleViewKeybinds():Void { - if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.LEFT) + if (currentLiveInputStyle == None) { - incrementDifficulty(-1); - } - if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.RIGHT) - { - incrementDifficulty(1); + if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.LEFT) + { + incrementDifficulty(-1); + } + if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.RIGHT) + { + incrementDifficulty(1); + } + // Would bind Ctrl+A and Ctrl+D here, but they are already bound to Select All and Select None. } } @@ -3237,7 +3287,7 @@ class ChartEditorState extends HaxeUIState */ function handleTestKeybinds():Void { - if (!isHaxeUIDialogOpen && FlxG.keys.justPressed.ENTER) + if (!isHaxeUIDialogOpen && !isCursorOverHaxeUI && FlxG.keys.justPressed.ENTER) { var minimal = FlxG.keys.pressed.SHIFT; testSongInPlayState(minimal); @@ -3829,25 +3879,26 @@ class ChartEditorState extends HaxeUIState switch (currentLiveInputStyle) { case LiveInputStyle.WASD: - if (FlxG.keys.justPressed.A) placeNoteAtPlayhead(0); - if (FlxG.keys.justPressed.S) placeNoteAtPlayhead(1); - if (FlxG.keys.justPressed.W) placeNoteAtPlayhead(2); - if (FlxG.keys.justPressed.D) placeNoteAtPlayhead(3); + if (FlxG.keys.justPressed.A) placeNoteAtPlayhead(4); + if (FlxG.keys.justPressed.S) placeNoteAtPlayhead(5); + if (FlxG.keys.justPressed.W) placeNoteAtPlayhead(6); + if (FlxG.keys.justPressed.D) placeNoteAtPlayhead(7); - if (FlxG.keys.justPressed.LEFT) placeNoteAtPlayhead(4); - if (FlxG.keys.justPressed.DOWN) placeNoteAtPlayhead(5); - if (FlxG.keys.justPressed.UP) placeNoteAtPlayhead(6); - if (FlxG.keys.justPressed.RIGHT) placeNoteAtPlayhead(7); + if (FlxG.keys.justPressed.LEFT) placeNoteAtPlayhead(0); + if (FlxG.keys.justPressed.DOWN) placeNoteAtPlayhead(1); + if (FlxG.keys.justPressed.UP) placeNoteAtPlayhead(2); + if (FlxG.keys.justPressed.RIGHT) placeNoteAtPlayhead(3); case LiveInputStyle.NumberKeys: - if (FlxG.keys.justPressed.ONE) placeNoteAtPlayhead(0); - if (FlxG.keys.justPressed.TWO) placeNoteAtPlayhead(1); - if (FlxG.keys.justPressed.THREE) placeNoteAtPlayhead(2); - if (FlxG.keys.justPressed.FOUR) placeNoteAtPlayhead(3); + // Flipped because Dad is on the left but represents data 0-3. + if (FlxG.keys.justPressed.ONE) placeNoteAtPlayhead(4); + if (FlxG.keys.justPressed.TWO) placeNoteAtPlayhead(5); + if (FlxG.keys.justPressed.THREE) placeNoteAtPlayhead(6); + if (FlxG.keys.justPressed.FOUR) placeNoteAtPlayhead(7); - if (FlxG.keys.justPressed.FIVE) placeNoteAtPlayhead(4); - if (FlxG.keys.justPressed.SIX) placeNoteAtPlayhead(5); - if (FlxG.keys.justPressed.SEVEN) placeNoteAtPlayhead(6); - if (FlxG.keys.justPressed.EIGHT) placeNoteAtPlayhead(7); + if (FlxG.keys.justPressed.FIVE) placeNoteAtPlayhead(0); + if (FlxG.keys.justPressed.SIX) placeNoteAtPlayhead(1); + if (FlxG.keys.justPressed.SEVEN) placeNoteAtPlayhead(2); + if (FlxG.keys.justPressed.EIGHT) placeNoteAtPlayhead(3); case LiveInputStyle.None: // Do nothing. } @@ -3856,12 +3907,24 @@ class ChartEditorState extends HaxeUIState function placeNoteAtPlayhead(column:Int):Void { var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels; - var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / (16 / noteSnapQuant); + var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / noteSnapRatio; var playheadPosStep:Int = Std.int(Math.floor(playheadPosFractionalStep)); - var playheadPosMs:Float = playheadPosStep * Conductor.stepLengthMs * (16 / noteSnapQuant); + var playheadPosSnappedMs:Float = playheadPosStep * Conductor.stepLengthMs * noteSnapRatio; - var newNoteData:SongNoteData = new SongNoteData(playheadPosMs, column, 0, selectedNoteKind); - performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); + // Look for notes within 1 step of the playhead. + var notesAtPos:Array = SongDataUtils.getNotesInTimeRange(currentSongChartNoteData, playheadPosSnappedMs, + playheadPosSnappedMs + Conductor.stepLengthMs * noteSnapRatio); + notesAtPos = SongDataUtils.getNotesWithData(notesAtPos, [column]); + + if (notesAtPos.length == 0) + { + var newNoteData:SongNoteData = new SongNoteData(playheadPosSnappedMs, column, 0, selectedNoteKind); + performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); + } + else + { + trace('Already a note there.'); + } } function set_scrollPositionInPixels(value:Float):Float @@ -3920,6 +3983,8 @@ class ChartEditorState extends HaxeUIState */ public function testSongInPlayState(minimal:Bool = false):Void { + autoSave(); + var startTimestamp:Float = 0; if (playtestStartTime) startTimestamp = scrollPositionInMs + playheadPositionInMs; diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index efabf10c3..28f864d0e 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -39,7 +39,7 @@ class Constants */ public static final VERSION_SUFFIX:String = ' PROTOTYPE'; - #if debug + #if (debug || FORCE_DEBUG_VERSION) static function get_VERSION():String { return 'v${Application.current.meta.get('version')} (${GIT_BRANCH} : ${GIT_HASH})' + VERSION_SUFFIX; @@ -71,7 +71,7 @@ class Constants */ // ============================== - #if debug + #if (debug || FORCE_DEBUG_VERSION) /** * The current Git branch. */ diff --git a/source/funkin/util/macro/GitCommit.hx b/source/funkin/util/macro/GitCommit.hx index 0449857cd..d0c034828 100644 --- a/source/funkin/util/macro/GitCommit.hx +++ b/source/funkin/util/macro/GitCommit.hx @@ -1,6 +1,6 @@ package funkin.util.macro; -#if debug +#if (debug || FORCE_DEBUG_VERSION) class GitCommit { /**