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
{
/**