From 9e27095659faa8a458516fc43fd6848653fe891a Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 19 Dec 2023 01:21:26 -0500 Subject: [PATCH 1/9] Update assets. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index c354795f7..6f17eb051 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c354795f7f560fa096b855c6e6bca745f77fa414 +Subproject commit 6f17eb051e2609d59a591d4e6eb78e37c6e90adb From 4ff5bd21df738f2b63e7679330afd56a0b53a975 Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 19 Dec 2023 01:23:42 -0500 Subject: [PATCH 2/9] Fixes to the FNF Legacy JSON parser --- source/funkin/data/DataParse.hx | 45 +++++++++++++++---- source/funkin/data/level/LevelRegistry.hx | 2 + .../data/notestyle/NoteStyleRegistry.hx | 2 + source/funkin/data/song/SongData.hx | 2 +- source/funkin/data/song/SongDataUtils.hx | 1 + source/funkin/data/song/SongRegistry.hx | 14 ++++++ .../data/song/importer/ChartManifestData.hx | 1 + .../data/song/importer/FNFLegacyData.hx | 3 +- .../data/song/importer/FNFLegacyImporter.hx | 22 ++++++++- .../source/funkin/data/BaseRegistryTest.hx | 2 + 10 files changed, 83 insertions(+), 11 deletions(-) diff --git a/source/funkin/data/DataParse.hx b/source/funkin/data/DataParse.hx index cbd168a61..49dde0198 100644 --- a/source/funkin/data/DataParse.hx +++ b/source/funkin/data/DataParse.hx @@ -178,7 +178,31 @@ class DataParse switch (json.value) { case JObject(fields): - return cast Tools.getValue(json); + var result:LegacyNoteSection = + { + mustHitSection: false, + sectionNotes: [], + }; + for (field in fields) + { + switch (field.name) + { + case 'sectionNotes': + result.sectionNotes = legacyNotes(field.value, field.name); + + case 'mustHitSection': + result.mustHitSection = Tools.getValue(field.value); + case 'typeOfSection': + result.typeOfSection = Tools.getValue(field.value); + case 'lengthInSteps': + result.lengthInSteps = Tools.getValue(field.value); + case 'changeBPM': + result.changeBPM = Tools.getValue(field.value); + case 'bpm': + result.bpm = Tools.getValue(field.value); + } + } + return result; default: throw 'Expected property $name to be an object, but it was ${json.value}.'; } @@ -189,7 +213,12 @@ class DataParse switch (json.value) { case JObject(fields): - return cast Tools.getValue(json); + var result = {}; + for (field in fields) + { + Reflect.setField(result, field.name, legacyNoteSectionArray(field.value, field.name)); + } + return result; default: throw 'Expected property $name to be an object, but it was ${json.value}.'; } @@ -211,13 +240,13 @@ class DataParse switch (json.value) { case JArray(values): - // var time:Null<Float> = values[0] == null ? null : Tools.getValue(values[0]); - // var data:Null<Int> = values[1] == null ? null : Tools.getValue(values[1]); - // var length:Null<Float> = values[2] == null ? null : Tools.getValue(values[2]); - // var alt:Null<Bool> = values[3] == null ? null : Tools.getValue(values[3]); + var time:Null<Float> = values[0] == null ? null : Tools.getValue(values[0]); + var data:Null<Int> = values[1] == null ? null : Tools.getValue(values[1]); + var length:Null<Float> = values[2] == null ? null : Tools.getValue(values[2]); + var alt:Null<Bool> = values[3] == null ? null : Tools.getValue(values[3]); - // return new LegacyNote(time, data, length, alt); - return null; + return new LegacyNote(time, data, length, alt); + // return null; default: throw 'Expected property $name to be a note, but it was ${json.value}.'; } diff --git a/source/funkin/data/level/LevelRegistry.hx b/source/funkin/data/level/LevelRegistry.hx index 75b0b11f6..b5c15de0f 100644 --- a/source/funkin/data/level/LevelRegistry.hx +++ b/source/funkin/data/level/LevelRegistry.hx @@ -30,6 +30,7 @@ class LevelRegistry extends BaseRegistry<Level, LevelData> // JsonParser does not take type parameters, // otherwise this function would be in BaseRegistry. var parser = new json2object.JsonParser<LevelData>(); + parser.ignoreUnknownVariables = false; switch (loadEntryFile(id)) { @@ -57,6 +58,7 @@ class LevelRegistry extends BaseRegistry<Level, LevelData> public function parseEntryDataRaw(contents:String, ?fileName:String):Null<LevelData> { var parser = new json2object.JsonParser<LevelData>(); + parser.ignoreUnknownVariables = false; parser.fromJson(contents, fileName); if (parser.errors.length > 0) diff --git a/source/funkin/data/notestyle/NoteStyleRegistry.hx b/source/funkin/data/notestyle/NoteStyleRegistry.hx index 4255a644b..ffb9bf490 100644 --- a/source/funkin/data/notestyle/NoteStyleRegistry.hx +++ b/source/funkin/data/notestyle/NoteStyleRegistry.hx @@ -35,6 +35,7 @@ class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData> // JsonParser does not take type parameters, // otherwise this function would be in BaseRegistry. var parser = new json2object.JsonParser<NoteStyleData>(); + parser.ignoreUnknownVariables = false; switch (loadEntryFile(id)) { @@ -62,6 +63,7 @@ class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData> public function parseEntryDataRaw(contents:String, ?fileName:String):Null<NoteStyleData> { var parser = new json2object.JsonParser<NoteStyleData>(); + parser.ignoreUnknownVariables = false; parser.fromJson(contents, fileName); if (parser.errors.length > 0) diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index 7886ada4f..600871e2f 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -747,7 +747,7 @@ class SongNoteDataRaw /** * The kind of the note. * This can allow the note to include information used for custom behavior. - * Defaults to blank or `"normal"`. + * Defaults to blank or `Constants.DEFAULT_DIFFICULTY`. */ @:alias("k") @:default("normal") diff --git a/source/funkin/data/song/SongDataUtils.hx b/source/funkin/data/song/SongDataUtils.hx index 4ae4b1426..309676884 100644 --- a/source/funkin/data/song/SongDataUtils.hx +++ b/source/funkin/data/song/SongDataUtils.hx @@ -230,6 +230,7 @@ class SongDataUtils trace('Read ${notesString.length} characters from clipboard.'); var parser = new json2object.JsonParser<SongClipboardItems>(); + parser.ignoreUnknownVariables = false; parser.fromJson(notesString, 'clipboard'); if (parser.errors.length > 0) { diff --git a/source/funkin/data/song/SongRegistry.hx b/source/funkin/data/song/SongRegistry.hx index 850654eb7..5a0835f57 100644 --- a/source/funkin/data/song/SongRegistry.hx +++ b/source/funkin/data/song/SongRegistry.hx @@ -126,6 +126,8 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> variation = variation == null ? Constants.DEFAULT_VARIATION : variation; var parser = new json2object.JsonParser<SongMetadata>(); + parser.ignoreUnknownVariables = false; + switch (loadEntryMetadataFile(id, variation)) { case {fileName: fileName, contents: contents}: @@ -147,6 +149,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> variation = variation == null ? Constants.DEFAULT_VARIATION : variation; var parser = new json2object.JsonParser<SongMetadata>(); + parser.ignoreUnknownVariables = false; parser.fromJson(contents, fileName); if (parser.errors.length > 0) @@ -206,6 +209,8 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> variation = variation == null ? Constants.DEFAULT_VARIATION : variation; var parser = new json2object.JsonParser<SongMetadata_v2_1_0>(); + parser.ignoreUnknownVariables = false; + switch (loadEntryMetadataFile(id, variation)) { case {fileName: fileName, contents: contents}: @@ -226,6 +231,8 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> variation = variation == null ? Constants.DEFAULT_VARIATION : variation; var parser = new json2object.JsonParser<SongMetadata_v2_0_0>(); + parser.ignoreUnknownVariables = false; + switch (loadEntryMetadataFile(id, variation)) { case {fileName: fileName, contents: contents}: @@ -244,6 +251,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> function parseEntryMetadataRaw_v2_1_0(contents:String, ?fileName:String = 'raw'):Null<SongMetadata> { var parser = new json2object.JsonParser<SongMetadata_v2_1_0>(); + parser.ignoreUnknownVariables = false; parser.fromJson(contents, fileName); if (parser.errors.length > 0) @@ -257,6 +265,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> function parseEntryMetadataRaw_v2_0_0(contents:String, ?fileName:String = 'raw'):Null<SongMetadata> { var parser = new json2object.JsonParser<SongMetadata_v2_0_0>(); + parser.ignoreUnknownVariables = false; parser.fromJson(contents, fileName); if (parser.errors.length > 0) @@ -272,6 +281,8 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> variation = variation == null ? Constants.DEFAULT_VARIATION : variation; var parser = new json2object.JsonParser<SongMusicData>(); + parser.ignoreUnknownVariables = false; + switch (loadMusicDataFile(id, variation)) { case {fileName: fileName, contents: contents}: @@ -291,6 +302,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> public function parseMusicDataRaw(contents:String, ?fileName:String = 'raw'):Null<SongMusicData> { var parser = new json2object.JsonParser<SongMusicData>(); + parser.ignoreUnknownVariables = false; parser.fromJson(contents, fileName); if (parser.errors.length > 0) @@ -334,6 +346,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> variation = variation == null ? Constants.DEFAULT_VARIATION : variation; var parser = new json2object.JsonParser<SongChartData>(); + parser.ignoreUnknownVariables = false; switch (loadEntryChartFile(id, variation)) { @@ -356,6 +369,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> variation = variation == null ? Constants.DEFAULT_VARIATION : variation; var parser = new json2object.JsonParser<SongChartData>(); + parser.ignoreUnknownVariables = false; parser.fromJson(contents, fileName); if (parser.errors.length > 0) diff --git a/source/funkin/data/song/importer/ChartManifestData.hx b/source/funkin/data/song/importer/ChartManifestData.hx index 0c7d2f0b0..dd0d28479 100644 --- a/source/funkin/data/song/importer/ChartManifestData.hx +++ b/source/funkin/data/song/importer/ChartManifestData.hx @@ -68,6 +68,7 @@ class ChartManifestData public static function deserialize(contents:String):Null<ChartManifestData> { var parser = new json2object.JsonParser<ChartManifestData>(); + parser.ignoreUnknownVariables = false; parser.fromJson(contents, 'manifest.json'); if (parser.errors.length > 0) diff --git a/source/funkin/data/song/importer/FNFLegacyData.hx b/source/funkin/data/song/importer/FNFLegacyData.hx index 5b75368c9..52380d344 100644 --- a/source/funkin/data/song/importer/FNFLegacyData.hx +++ b/source/funkin/data/song/importer/FNFLegacyData.hx @@ -19,7 +19,8 @@ class LegacySongData @:jcustomparse(funkin.data.DataParse.eitherLegacyScrollSpeeds) public var speed:Either<Float, LegacyScrollSpeeds>; - public var stageDefault:String; + @:optional + public var stageDefault:Null<String>; public var bpm:Float; @:jcustomparse(funkin.data.DataParse.eitherLegacyNoteData) diff --git a/source/funkin/data/song/importer/FNFLegacyImporter.hx b/source/funkin/data/song/importer/FNFLegacyImporter.hx index ee68513dc..ab2abda8e 100644 --- a/source/funkin/data/song/importer/FNFLegacyImporter.hx +++ b/source/funkin/data/song/importer/FNFLegacyImporter.hx @@ -14,6 +14,7 @@ class FNFLegacyImporter public static function parseLegacyDataRaw(input:String, fileName:String = 'raw'):FNFLegacyData { var parser = new json2object.JsonParser<FNFLegacyData>(); + parser.ignoreUnknownVariables = true; // Set to true to ignore extra variables that might be included in the JSON. parser.fromJson(input, fileName); if (parser.errors.length > 0) @@ -185,15 +186,34 @@ class FNFLegacyImporter return result; } + static final STRUMLINE_SIZE = 4; + static function migrateNoteSections(input:Array<LegacyNoteSection>):Array<SongNoteData> { var result:Array<SongNoteData> = []; for (section in input) { + var mustHitSection = section.mustHitSection ?? false; for (note in section.sectionNotes) { - result.push(new SongNoteData(note.time, note.data, note.length, note.getKind())); + // Handle the dumb logic for mustHitSection. + var noteData = note.data; + + // Flip notes if mustHitSection is FALSE (not true lol). + if (!mustHitSection) + { + if (noteData >= STRUMLINE_SIZE) + { + noteData -= STRUMLINE_SIZE; + } + else + { + noteData += STRUMLINE_SIZE; + } + } + + result.push(new SongNoteData(note.time, noteData, note.length, note.getKind())); } } diff --git a/tests/unit/source/funkin/data/BaseRegistryTest.hx b/tests/unit/source/funkin/data/BaseRegistryTest.hx index 0be932d35..5f837ba97 100644 --- a/tests/unit/source/funkin/data/BaseRegistryTest.hx +++ b/tests/unit/source/funkin/data/BaseRegistryTest.hx @@ -156,6 +156,7 @@ class MyTypeRegistry extends BaseRegistry<MyType, MyTypeData> // JsonParser does not take type parameters, // otherwise this function would be in BaseRegistry. var parser = new json2object.JsonParser<MyTypeData>(); + parser.ignoreUnknownVariables = false; switch (loadEntryFile(id)) { @@ -181,6 +182,7 @@ class MyTypeRegistry extends BaseRegistry<MyType, MyTypeData> // JsonParser does not take type parameters, // otherwise this function would be in BaseRegistry. var parser = new json2object.JsonParser<MyTypeData_v0_1_x>(); + parser.ignoreUnknownVariables = false; switch (loadEntryFile(id)) { From 328bb7b938d65406926cf268a2b47fd78fc60870 Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 19 Dec 2023 01:25:15 -0500 Subject: [PATCH 3/9] Fixes to Erect/Nightmare only --- source/funkin/input/Cursor.hx | 12 ++++++++++++ source/funkin/play/stage/StageData.hx | 1 + source/funkin/ui/debug/charting/ChartEditorState.hx | 6 ++++-- .../charting/handlers/ChartEditorDialogHandler.hx | 3 +++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/source/funkin/input/Cursor.hx b/source/funkin/input/Cursor.hx index b4bf43808..39f399465 100644 --- a/source/funkin/input/Cursor.hx +++ b/source/funkin/input/Cursor.hx @@ -34,6 +34,18 @@ class Cursor Cursor.cursorMode = null; } + public static inline function toggle():Void + { + if (FlxG.mouse.visible) + { + hide(); + } + else + { + show(); + } + } + public static final CURSOR_DEFAULT_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-default.png", diff --git a/source/funkin/play/stage/StageData.hx b/source/funkin/play/stage/StageData.hx index d89995ef3..2d87dec31 100644 --- a/source/funkin/play/stage/StageData.hx +++ b/source/funkin/play/stage/StageData.hx @@ -164,6 +164,7 @@ class StageDataParser try { var parser = new json2object.JsonParser<StageData>(); + parser.ignoreUnknownVariables = false; parser.fromJson(rawJson, '$stageId.json'); if (parser.errors.length > 0) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index fa55750bf..afb0a114d 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1010,7 +1010,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function get_availableDifficulties():Array<String> { var m:Null<SongMetadata> = songMetadata.get(selectedVariation); - return m?.playData?.difficulties ?? []; + return m?.playData?.difficulties ?? [Constants.DEFAULT_DIFFICULTY]; } /** @@ -1069,7 +1069,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var result:Null<SongChartData> = songChartData.get(selectedVariation); if (result == null) { - result = new SongChartData(["normal" => 1.0], [], ["normal" => []]); + result = new SongChartData([Constants.DEFAULT_DIFFICULTY => 1.0], [], [Constants.DEFAULT_DIFFICULTY => []]); songChartData.set(selectedVariation, result); } return result; @@ -1293,6 +1293,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function set_selectedDifficulty(value:String):String { + if (value == null) value = availableDifficulties[0] ?? Constants.DEFAULT_DIFFICULTY; + selectedDifficulty = value; // Make sure view is updated when the difficulty changes. diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx index 666b3656c..a595b8195 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx @@ -687,6 +687,9 @@ class ChartEditorDialogHandler Conductor.instrumentalOffset = state.currentInstrumentalOffset; // Loads from the metadata. Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges); + state.selectedVariation = Constants.DEFAULT_VARIATION; + state.selectedDifficulty = state.availableDifficulties[0]; + state.difficultySelectDirty = true; dialog.hideDialog(DialogButton.APPLY); From 3e65e7ecc59970d6060bd6f54f6097395d16f24a Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 19 Dec 2023 01:26:26 -0500 Subject: [PATCH 4/9] Fix for vocals not loading properly and not getting cleared properly. --- .../ui/debug/charting/ChartEditorState.hx | 23 +++++++++++++--- .../handlers/ChartEditorAudioHandler.hx | 27 ++++++++++--------- .../handlers/ChartEditorDialogHandler.hx | 14 +++------- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index afb0a114d..8369e95b9 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2548,8 +2548,25 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState menubarItemPlayPause.onClick = _ -> toggleAudioPlayback(); - menubarItemLoadInstrumental.onClick = _ -> this.openUploadInstDialog(true); - menubarItemLoadVocals.onClick = _ -> this.openUploadVocalsDialog(true); + menubarItemLoadInstrumental.onClick = _ -> { + var dialog = this.openUploadInstDialog(true); + // Ensure instrumental and vocals are reloaded properly. + dialog.onDialogClosed = function(_) { + this.isHaxeUIDialogOpen = false; + this.switchToCurrentInstrumental(); + this.postLoadInstrumental(); + } + }; + + menubarItemLoadVocals.onClick = _ -> { + var dialog = this.openUploadVocalsDialog(true); + // Ensure instrumental and vocals are reloaded properly. + dialog.onDialogClosed = function(_) { + this.isHaxeUIDialogOpen = false; + this.switchToCurrentInstrumental(); + this.postLoadInstrumental(); + } + }; menubarItemVolumeMetronome.onChange = event -> { var volume:Float = event.value.toFloat() / 100.0; @@ -4047,7 +4064,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } else { - // If we clicked and released outside the grid, do nothing. + // If we clicked and released outside the grid (or on HaxeUI), do nothing. } } diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx index 272291a94..990ab41ae 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx @@ -28,11 +28,11 @@ class ChartEditorAudioHandler * @param instId The instrumental this vocal track will be for. * @return Success or failure. */ - public static function loadVocalsFromPath(state:ChartEditorState, path:Path, charId:String, instId:String = ''):Bool + public static function loadVocalsFromPath(state:ChartEditorState, path:Path, charId:String, instId:String = '', wipeFirst:Bool = false):Bool { #if sys var fileBytes:Bytes = sys.io.File.getBytes(path.toString()); - return loadVocalsFromBytes(state, fileBytes, charId, instId); + return loadVocalsFromBytes(state, fileBytes, charId, instId, wipeFirst); #else trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way."); return false; @@ -47,12 +47,12 @@ class ChartEditorAudioHandler * @param instId The instrumental this vocal track will be for. * @return Success or failure. */ - public static function loadVocalsFromAsset(state:ChartEditorState, path:String, charId:String, instId:String = ''):Bool + public static function loadVocalsFromAsset(state:ChartEditorState, path:String, charId:String, instId:String = '', wipeFirst:Bool = false):Bool { var trackData:Null<Bytes> = Assets.getBytes(path); if (trackData != null) { - return loadVocalsFromBytes(state, trackData, charId, instId); + return loadVocalsFromBytes(state, trackData, charId, instId, wipeFirst); } return false; } @@ -63,10 +63,12 @@ class ChartEditorAudioHandler * @param bytes The audio byte data. * @param charId The character this vocal track will be for. * @param instId The instrumental this vocal track will be for. + * @param wipeFirst Whether to wipe the existing vocal data before loading. */ - public static function loadVocalsFromBytes(state:ChartEditorState, bytes:Bytes, charId:String, instId:String = ''):Bool + public static function loadVocalsFromBytes(state:ChartEditorState, bytes:Bytes, charId:String, instId:String = '', wipeFirst:Bool = false):Bool { var trackId:String = '${charId}${instId == '' ? '' : '-${instId}'}'; + if (wipeFirst) wipeVocalData(state); state.audioVocalTrackData.set(trackId, bytes); return true; } @@ -78,11 +80,11 @@ class ChartEditorAudioHandler * @param instId The instrumental this vocal track will be for. * @return Success or failure. */ - public static function loadInstFromPath(state:ChartEditorState, path:Path, instId:String = ''):Bool + public static function loadInstFromPath(state:ChartEditorState, path:Path, instId:String = '', wipeFirst:Bool = false):Bool { #if sys var fileBytes:Bytes = sys.io.File.getBytes(path.toString()); - return loadInstFromBytes(state, fileBytes, instId); + return loadInstFromBytes(state, fileBytes, instId, wipeFirst); #else trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way."); return false; @@ -96,12 +98,12 @@ class ChartEditorAudioHandler * @param instId The instrumental this vocal track will be for. * @return Success or failure. */ - public static function loadInstFromAsset(state:ChartEditorState, path:String, instId:String = ''):Bool + public static function loadInstFromAsset(state:ChartEditorState, path:String, instId:String = '', wipeFirst:Bool = false):Bool { var trackData:Null<Bytes> = Assets.getBytes(path); if (trackData != null) { - return loadInstFromBytes(state, trackData, instId); + return loadInstFromBytes(state, trackData, instId, wipeFirst); } return false; } @@ -113,9 +115,10 @@ class ChartEditorAudioHandler * @param charId The character this vocal track will be for. * @param instId The instrumental this vocal track will be for. */ - public static function loadInstFromBytes(state:ChartEditorState, bytes:Bytes, instId:String = ''):Bool + public static function loadInstFromBytes(state:ChartEditorState, bytes:Bytes, instId:String = '', wipeFirst:Bool = false):Bool { if (instId == '') instId = 'default'; + if (wipeFirst) wipeInstrumentalData(state); state.audioInstTrackData.set(instId, bytes); return true; } @@ -127,9 +130,9 @@ class ChartEditorAudioHandler stopExistingVocals(state); result = playVocals(state, BF, playerId, instId); - if (!result) return false; + // if (!result) return false; result = playVocals(state, DAD, opponentId, instId); - if (!result) return false; + // if (!result) return false; return true; } diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx index a595b8195..2ede1a39f 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx @@ -758,14 +758,9 @@ class ChartEditorDialogHandler trace('Selected file: $pathStr'); var path:Path = new Path(pathStr); - if (!hasClearedVocals) + if (state.loadVocalsFromPath(path, charKey, instId, !hasClearedVocals)) { hasClearedVocals = true; - state.stopExistingVocals(); - } - - if (state.loadVocalsFromPath(path, charKey, instId)) - { // Tell the user the load was successful. state.success('Loaded Vocals', 'Loaded vocals for $charName (${path.file}.${path.ext}), variation ${state.selectedVariation}'); #if FILE_DROP_SUPPORTED @@ -799,13 +794,10 @@ class ChartEditorDialogHandler if (selectedFile != null && selectedFile.bytes != null) { trace('Selected file: ' + selectedFile.name); - if (!hasClearedVocals) + + if (state.loadVocalsFromBytes(selectedFile.bytes, charKey, instId, !hasClearedVocals)) { hasClearedVocals = true; - state.stopExistingVocals(); - } - if (state.loadVocalsFromBytes(selectedFile.bytes, charKey, instId)) - { // Tell the user the load was successful. state.success('Loaded Vocals', 'Loaded vocals for $charName (${selectedFile.name}), variation ${state.selectedVariation}'); From bb0fb0281372c5843995a19cda7a9bba5545783f Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 19 Dec 2023 01:26:43 -0500 Subject: [PATCH 5/9] Fix to launching directly into Chart Editor --- source/funkin/Conductor.hx | 14 +++++++------- .../funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index c531678ad..7b34bffe2 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -37,7 +37,7 @@ class Conductor /** * The most recent time change for the current song position. */ - public static var currentTimeChange(default, null):SongTimeChange; + public static var currentTimeChange(default, null):Null<SongTimeChange>; /** * The current position in the song in milliseconds. @@ -132,32 +132,32 @@ class Conductor /** * Current position in the song, in measures. */ - public static var currentMeasure(default, null):Int; + public static var currentMeasure(default, null):Int = 0; /** * Current position in the song, in beats. */ - public static var currentBeat(default, null):Int; + public static var currentBeat(default, null):Int = 0; /** * Current position in the song, in steps. */ - public static var currentStep(default, null):Int; + public static var currentStep(default, null):Int = 0; /** * Current position in the song, in measures and fractions of a measure. */ - public static var currentMeasureTime(default, null):Float; + public static var currentMeasureTime(default, null):Float = 0; /** * Current position in the song, in beats and fractions of a measure. */ - public static var currentBeatTime(default, null):Float; + public static var currentBeatTime(default, null):Float = 0; /** * Current position in the song, in steps and fractions of a step. */ - public static var currentStepTime(default, null):Float; + public static var currentStepTime(default, null):Float = 0; /** * An offset tied to the current chart file to compensate for a delay in the instrumental. diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 8369e95b9..de38a8fda 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -4387,7 +4387,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState playbarNoteSnap.text = '1/${noteSnapQuant}'; playbarDifficulty.text = "Difficulty: " + selectedDifficulty.toTitleCase(); - playbarBPM.text = "BPM: " + Conductor.currentTimeChange.bpm; + playbarBPM.text = "BPM: " + (Conductor.currentTimeChange?.bpm ?? 0.0); } function handlePlayhead():Void From ad02bf2ee0c4d0bc8437069ada3d19fd0ab156dc Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 19 Dec 2023 01:27:58 -0500 Subject: [PATCH 6/9] Fix to GameOverSubstate exiting to Freeplay instead of Chart Editor --- source/funkin/play/GameOverSubState.hx | 24 ++++++++++++++++++++-- source/funkin/play/PlayState.hx | 5 ++++- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/story/StoryMenuState.hx | 2 +- source/funkin/util/Constants.hx | 1 + 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index 6eb53e2d5..18e3e0280 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -64,9 +64,13 @@ class GameOverSubState extends MusicBeatSubState */ var isEnding:Bool = false; - public function new() + var isChartingMode:Bool = false; + + public function new(?params:GameOverParams) { super(); + + this.isChartingMode = params?.isChartingMode ?? false; } /** @@ -176,9 +180,20 @@ class GameOverSubState extends MusicBeatSubState // PlayState.seenCutscene = false; // old thing... gameOverMusic.stop(); - if (PlayStatePlaylist.isStoryMode) FlxG.switchState(new StoryMenuState()); + if (isChartingMode) + { + this.close(); + if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position! + PlayState.instance.close(); // This only works because PlayState is a substate! + } + else if (PlayStatePlaylist.isStoryMode) + { + FlxG.switchState(new StoryMenuState()); + } else + { FlxG.switchState(new FreeplayState()); + } } if (gameOverMusic.playing) @@ -307,3 +322,8 @@ class GameOverSubState extends MusicBeatSubState }); } } + +typedef GameOverParams = +{ + var isChartingMode:Bool; +} diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index e0932e756..c834e0abe 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -922,7 +922,10 @@ class PlayState extends MusicBeatSubState } #end - var gameOverSubState = new GameOverSubState(); + var gameOverSubState = new GameOverSubState( + { + isChartingMode: isChartingMode + }); FlxTransitionableSubState.skipNextTransIn = true; FlxTransitionableSubState.skipNextTransOut = true; openSubState(gameOverSubState); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7c69804d9..f17c3d91e 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -97,7 +97,7 @@ class FreeplayState extends MusicBeatSubState var stickerSubState:StickerSubState; // - static var rememberedDifficulty:Null<String> = "normal"; + static var rememberedDifficulty:Null<String> = Constants.DEFAULT_DIFFICULTY; static var rememberedSongId:Null<String> = null; public function new(?stickers:StickerSubState = null) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 456988873..6e4cdacaf 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -106,7 +106,7 @@ class StoryMenuState extends MusicBeatState var stickerSubState:StickerSubState; static var rememberedLevelId:Null<String> = null; - static var rememberedDifficulty:Null<String> = "normal"; + static var rememberedDifficulty:Null<String> = Constants.DEFAULT_DIFFICULTY; public function new(?stickers:StickerSubState = null) { diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index f8749567b..123267a49 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -123,6 +123,7 @@ class Constants /** * Default list of difficulties for charts. + * Assumes no Erect mode, etc. */ public static final DEFAULT_DIFFICULTY_LIST:Array<String> = ['easy', 'normal', 'hard']; From 70b7de94aa672bd607583c5763bf6e2d8921369c Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 19 Dec 2023 01:28:13 -0500 Subject: [PATCH 7/9] Fix to Metadata toolbox causing crash when no GF :( --- .../toolboxes/ChartEditorMetadataToolbox.hx | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx index 509aa5b07..bc9384cf3 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx @@ -183,17 +183,41 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox var LIMIT = 6; - var charDataOpponent:CharacterData = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.opponent); - buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.opponent); - buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}'; + var charDataOpponent:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.opponent); + if (charDataOpponent != null) + { + buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.opponent); + buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}'; + } + else + { + buttonCharacterOpponent.icon = null; + buttonCharacterOpponent.text = "None"; + } - var charDataGirlfriend:CharacterData = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.girlfriend); - buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.girlfriend); - buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}'; + var charDataGirlfriend:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.girlfriend); + if (charDataGirlfriend != null) + { + buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.girlfriend); + buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}'; + } + else + { + buttonCharacterGirlfriend.icon = null; + buttonCharacterGirlfriend.text = "None"; + } - var charDataPlayer:CharacterData = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.player); - buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.player); - buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}'; + var charDataPlayer:Null<CharacterData> = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.player); + if (charDataPlayer != null) + { + buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.player); + buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}'; + } + else + { + buttonCharacterPlayer.icon = null; + buttonCharacterPlayer.text = "None"; + } } public static function build(chartEditorState:ChartEditorState):ChartEditorMetadataToolbox From f01535e43165e9e0f833d6b9c283480af5c26e9d Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Tue, 19 Dec 2023 01:28:24 -0500 Subject: [PATCH 8/9] Don't forget to update hmm! --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 96ee75bc1..8a903eed6 100644 --- a/hmm.json +++ b/hmm.json @@ -100,7 +100,7 @@ "name": "json2object", "type": "git", "dir": null, - "ref": "a0a78b60c41e47bae8bfa422488a199a58b4474e", + "ref": "a8c26f18463c98da32f744c214fe02273e1823fa", "url": "https://github.com/FunkinCrew/json2object" }, { From 92e0022fedcba609bb1d5320c2cffc6d70708676 Mon Sep 17 00:00:00 2001 From: Cameron Taylor <cameron.taylor.ninja@gmail.com> Date: Mon, 1 Jan 2024 19:13:51 -0500 Subject: [PATCH 9/9] derp comma! --- source/funkin/play/PlayState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index ea38d833f..3dcabf953 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -924,8 +924,8 @@ class PlayState extends MusicBeatSubState var gameOverSubState = new GameOverSubState( { - isChartingMode: isChartingMode - transparent: persistentDraw, + isChartingMode: isChartingMode, + transparent: persistentDraw }); FlxTransitionableSubState.skipNextTransIn = true; FlxTransitionableSubState.skipNextTransOut = true;