From c6a1f5ffeac51686b23b4764edeb569a173e910e Mon Sep 17 00:00:00 2001 From: EliteMasterEric <ericmyllyoja@gmail.com> Date: Fri, 11 Aug 2023 14:00:38 -0400 Subject: [PATCH] Work on fixing issues with difficulty/variation handling in charts --- source/funkin/MainMenuState.hx | 2 +- source/funkin/play/song/SongData.hx | 17 ++++----- .../charting/ChartEditorDialogHandler.hx | 7 +++- .../ui/debug/charting/ChartEditorState.hx | 10 ++++-- .../charting/ChartEditorToolboxHandler.hx | 6 +++- source/funkin/util/SerializerUtil.hx | 11 +++++- source/funkin/util/SortUtil.hx | 35 ++++++++++++++++++- 7 files changed, 70 insertions(+), 18 deletions(-) diff --git a/source/funkin/MainMenuState.hx b/source/funkin/MainMenuState.hx index fc493ef4b..5a69ea83a 100644 --- a/source/funkin/MainMenuState.hx +++ b/source/funkin/MainMenuState.hx @@ -54,7 +54,7 @@ class MainMenuState extends MusicBeatState transIn = FlxTransitionableState.defaultTransIn; transOut = FlxTransitionableState.defaultTransOut; - if (!FlxG.sound.music.playing) + if (!(FlxG?.sound?.music?.playing ?? false)) { FlxG.sound.playMusic(Paths.music('freakyMenu/freakyMenu')); } diff --git a/source/funkin/play/song/SongData.hx b/source/funkin/play/song/SongData.hx index fbd7e3383..938ee0708 100644 --- a/source/funkin/play/song/SongData.hx +++ b/source/funkin/play/song/SongData.hx @@ -11,6 +11,7 @@ import haxe.DynamicAccess; import haxe.Json; import openfl.utils.Assets; import thx.semver.Version; +import funkin.util.SerializerUtil; /** * Contains utilities for loading and parsing stage data. @@ -138,13 +139,8 @@ class SongDataParser { var result:Array<SongMetadata> = []; - var rawJson:String = loadSongMetadataFile(songId); - var jsonData:Dynamic = null; - try - { - jsonData = Json.parse(rawJson); - } - catch (e) {} + var jsonStr:String = loadSongMetadataFile(songId); + var jsonData:Dynamic = SerializerUtil.fromJSON(jsonStr); var songMetadata:SongMetadata = SongMigrator.migrateSongMetadata(jsonData, songId); songMetadata = SongValidator.validateSongMetadata(songMetadata, songId); @@ -160,9 +156,10 @@ class SongDataParser for (variation in variations) { - var variationRawJson:String = loadSongMetadataFile(songId, variation); - var variationSongMetadata:SongMetadata = SongMigrator.migrateSongMetadata(variationRawJson, '${songId}_${variation}'); - variationSongMetadata = SongValidator.validateSongMetadata(variationSongMetadata, '${songId}_${variation}'); + var variationJsonStr:String = loadSongMetadataFile(songId, variation); + var variationJsonData:Dynamic = SerializerUtil.fromJSON(variationJsonStr); + var variationSongMetadata:SongMetadata = SongMigrator.migrateSongMetadata(variationJsonData, '${songId}:${variation}'); + variationSongMetadata = SongValidator.validateSongMetadata(variationSongMetadata, '${songId}:${variation}'); if (variationSongMetadata != null) { variationSongMetadata.variation = variation; diff --git a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx index 6641a16c0..43e8ac96c 100644 --- a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx @@ -115,7 +115,12 @@ class ChartEditorDialogHandler if (songData == null) continue; - var songName:String = songData.getDifficulty().songName; + var songName:Null<String> = songData.getDifficulty('normal') ?.songName; + if (songName == null) songName = songData.getDifficulty() ?.songName; + if (songName == null) + { + trace('[WARN] Could not fetch song name for ${targetSongId}'); + } var linkTemplateSong:Link = new Link(); linkTemplateSong.text = songName; diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 26b001d7e..da8dd2d86 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2804,7 +2804,10 @@ class ChartEditorState extends HaxeUIState var treeSong:TreeViewNode = treeView.addNode({id: 'stv_song', text: 'S: $currentSongName', icon: 'haxeui-core/styles/default/haxeui_tiny.png'}); treeSong.expanded = true; - for (curVariation in availableVariations) + var variations = Reflect.copy(availableVariations); + variations.sort(SortUtil.alphabetically); + + for (curVariation in variations) { var variationMetadata:SongMetadata = songMetadata.get(curVariation); @@ -2940,13 +2943,14 @@ class ChartEditorState extends HaxeUIState function getCurrentTreeDifficultyNode():TreeViewNode { - var treeView:TreeView = findComponent('difficultyToolboxTree'); + var difficultyToolbox:CollapsibleDialog = ChartEditorToolboxHandler.getToolbox(this, CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT); + if (difficultyToolbox == null) return null; + var treeView:TreeView = difficultyToolbox.findComponent('difficultyToolboxTree'); if (treeView == null) return null; var result:TreeViewNode = treeView.findNodeByPath('stv_song/stv_variation_$selectedVariation/stv_difficulty_${selectedVariation}_$selectedDifficulty', 'id'); - if (result == null) return null; return result; diff --git a/source/funkin/ui/debug/charting/ChartEditorToolboxHandler.hx b/source/funkin/ui/debug/charting/ChartEditorToolboxHandler.hx index 5cace2ff6..d35323f1b 100644 --- a/source/funkin/ui/debug/charting/ChartEditorToolboxHandler.hx +++ b/source/funkin/ui/debug/charting/ChartEditorToolboxHandler.hx @@ -489,6 +489,8 @@ class ChartEditorToolboxHandler }; inputBPM.value = state.currentSongMetadata.timeChanges[0].bpm; + var labelScrollSpeed:Label = toolbox.findComponent('labelScrollSpeed', Label); + var inputScrollSpeed:Slider = toolbox.findComponent('inputScrollSpeed', Slider); inputScrollSpeed.onChange = function(event:UIEvent) { var valid:Bool = event.target.value != null && event.target.value > 0; @@ -502,8 +504,10 @@ class ChartEditorToolboxHandler { state.currentSongChartScrollSpeed = 1.0; } + labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x'; }; - inputScrollSpeed.value = state.currentSongChartData.scrollSpeed; + inputScrollSpeed.value = state.currentSongChartScrollSpeed; + labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x'; return toolbox; } diff --git a/source/funkin/util/SerializerUtil.hx b/source/funkin/util/SerializerUtil.hx index 9452b7785..d731aee8f 100644 --- a/source/funkin/util/SerializerUtil.hx +++ b/source/funkin/util/SerializerUtil.hx @@ -36,7 +36,16 @@ class SerializerUtil */ public static function fromJSON(input:String):Dynamic { - return Json.parse(input); + try + { + return Json.parse(input); + } + catch (e) + { + trace('An error occurred while parsing JSON from string data'); + trace(e); + return null; + } } /** diff --git a/source/funkin/util/SortUtil.hx b/source/funkin/util/SortUtil.hx index 61418c299..082de4b41 100644 --- a/source/funkin/util/SortUtil.hx +++ b/source/funkin/util/SortUtil.hx @@ -30,8 +30,10 @@ class SortUtil /** * Sort predicate for sorting strings alphabetically. + * @param a The first string to compare. + * @param b The second string to compare. */ - public static function alphabetically(a:String, b:String) + public static function alphabetically(a:String, b:String):Int { a = a.toUpperCase(); b = b.toUpperCase(); @@ -39,4 +41,35 @@ class SortUtil // Sort alphabetically. Yes that's how this works. return a == b ? 0 : a > b ? 1 : -1; } + + /** + * Sort predicate which sorts two strings alphabetically, but prioritizes a specific string first. + * Example usage: `array.sort(defaultThenAlphabetical.bind('test'))` will sort the array so that the string 'test' is first. + * @param a The first string to compare. + * @param b The second string to compare. + * @param defaultValue The value to prioritize. Defaults to `default`. + */ + public static function defaultThenAlphabetically(a:String, b:String, defaultValue:String):Int + { + if (a == b) return 0; + if (a == defaultValue) return 1; + if (b == defaultValue) return -1; + return alphabetically(a, b); + } + + /** + * Sort predicate which sorts two strings alphabetically, but prioritizes a specific string first. + * Example usage: `array.sort(defaultsThenAlphabetical.bind(['test']))` will sort the array so that the string 'test' is first. + * @param a The first string to compare. + * @param b The second string to compare. + * @param defaultValue The value to prioritize. Defaults to `default`. + */ + public static function defaultsThenAlphabetically(a:String, b:String, defaultValues:Array<String>):Int + { + if (a == b) return 0; + if (defaultValues.contains(a) && defaultValues.contains(b)) return alphabetically(a, b); + if (defaultValues.contains(a)) return 1; + if (defaultValues.contains(b)) return -1; + return alphabetically(a, b); + } }