diff --git a/assets b/assets index fd112e293..778e16705 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fd112e293ee0f823ee98d5b8bd8a85e934f772f6 +Subproject commit 778e16705b30af85087f627594c22f4b5ba6141a diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index 26380947a..bd25139a7 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -30,6 +30,9 @@ class SongMetadata implements ICloneable<SongMetadata> @:default("Unknown") public var artist:String; + @:optional + public var charter:Null<String> = null; + @:optional @:default(96) public var divisions:Null<Int>; // Optional field diff --git a/source/funkin/data/song/SongRegistry.hx b/source/funkin/data/song/SongRegistry.hx index 277dcd9e1..a3305c4ec 100644 --- a/source/funkin/data/song/SongRegistry.hx +++ b/source/funkin/data/song/SongRegistry.hx @@ -20,7 +20,7 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata> * Handle breaking changes by incrementing this value * and adding migration to the `migrateStageData()` function. */ - public static final SONG_METADATA_VERSION:thx.semver.Version = "2.2.2"; + public static final SONG_METADATA_VERSION:thx.semver.Version = "2.2.3"; public static final SONG_METADATA_VERSION_RULE:thx.semver.VersionRule = "2.2.x"; diff --git a/source/funkin/data/song/importer/FNFLegacyImporter.hx b/source/funkin/data/song/importer/FNFLegacyImporter.hx index ab2abda8e..fdfac7f72 100644 --- a/source/funkin/data/song/importer/FNFLegacyImporter.hx +++ b/source/funkin/data/song/importer/FNFLegacyImporter.hx @@ -36,7 +36,7 @@ class FNFLegacyImporter { trace('Migrating song metadata from FNF Legacy.'); - var songMetadata:SongMetadata = new SongMetadata('Import', 'Kawai Sprite', 'default'); + var songMetadata:SongMetadata = new SongMetadata('Import', Constants.DEFAULT_ARTIST, 'default'); var hadError:Bool = false; diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index fb9d9b4e2..c345871a9 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -101,6 +101,10 @@ class PauseSubState extends MusicBeatSubState */ static final MUSIC_FINAL_VOLUME:Float = 0.75; + static final CHARTER_FADE_DELAY:Float = 15.0; + + static final CHARTER_FADE_DURATION:Float = 0.75; + /** * Defines which pause music to use. */ @@ -163,6 +167,12 @@ class PauseSubState extends MusicBeatSubState */ var metadataDeaths:FlxText; + /** + * A text object which displays the current song's artist. + * Fades to the charter after a period before fading back. + */ + var metadataArtist:FlxText; + /** * The actual text objects for the menu entries. */ @@ -203,6 +213,8 @@ class PauseSubState extends MusicBeatSubState regenerateMenu(); transitionIn(); + + startCharterTimer(); } /** @@ -222,6 +234,8 @@ class PauseSubState extends MusicBeatSubState public override function destroy():Void { super.destroy(); + charterFadeTween.destroy(); + charterFadeTween = null; pauseMusic.stop(); } @@ -270,16 +284,25 @@ class PauseSubState extends MusicBeatSubState metadata.scrollFactor.set(0, 0); add(metadata); - var metadataSong:FlxText = new FlxText(20, 15, FlxG.width - 40, 'Song Name - Artist'); + var metadataSong:FlxText = new FlxText(20, 15, FlxG.width - 40, 'Song Name'); metadataSong.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); if (PlayState.instance?.currentChart != null) { - metadataSong.text = '${PlayState.instance.currentChart.songName} - ${PlayState.instance.currentChart.songArtist}'; + metadataSong.text = '${PlayState.instance.currentChart.songName}'; } metadataSong.scrollFactor.set(0, 0); metadata.add(metadataSong); - var metadataDifficulty:FlxText = new FlxText(20, 15 + 32, FlxG.width - 40, 'Difficulty: '); + metadataArtist = new FlxText(20, metadataSong.y + 32, FlxG.width - 40, 'Artist: ${Constants.DEFAULT_ARTIST}'); + metadataArtist.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); + if (PlayState.instance?.currentChart != null) + { + metadataArtist.text = 'Artist: ${PlayState.instance.currentChart.songArtist}'; + } + metadataArtist.scrollFactor.set(0, 0); + metadata.add(metadataArtist); + + var metadataDifficulty:FlxText = new FlxText(20, metadataArtist.y + 32, FlxG.width - 40, 'Difficulty: '); metadataDifficulty.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); if (PlayState.instance?.currentDifficulty != null) { @@ -288,12 +311,12 @@ class PauseSubState extends MusicBeatSubState metadataDifficulty.scrollFactor.set(0, 0); metadata.add(metadataDifficulty); - metadataDeaths = new FlxText(20, 15 + 64, FlxG.width - 40, '${PlayState.instance?.deathCounter} Blue Balls'); + metadataDeaths = new FlxText(20, metadataDifficulty.y + 32, FlxG.width - 40, '${PlayState.instance?.deathCounter} Blue Balls'); metadataDeaths.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); metadataDeaths.scrollFactor.set(0, 0); metadata.add(metadataDeaths); - metadataPractice = new FlxText(20, 15 + 96, FlxG.width - 40, 'PRACTICE MODE'); + metadataPractice = new FlxText(20, metadataDeaths.y + 32, FlxG.width - 40, 'PRACTICE MODE'); metadataPractice.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); metadataPractice.visible = PlayState.instance?.isPracticeMode ?? false; metadataPractice.scrollFactor.set(0, 0); @@ -302,6 +325,62 @@ class PauseSubState extends MusicBeatSubState updateMetadataText(); } + var charterFadeTween:Null<FlxTween> = null; + + function startCharterTimer():Void + { + charterFadeTween = FlxTween.tween(metadataArtist, {alpha: 0.0}, CHARTER_FADE_DURATION, + { + startDelay: CHARTER_FADE_DELAY, + ease: FlxEase.quartOut, + onComplete: (_) -> { + if (PlayState.instance?.currentChart != null) + { + metadataArtist.text = 'Charter: ${PlayState.instance.currentChart.charter ?? 'Unknown'}'; + } + else + { + metadataArtist.text = 'Charter: ${Constants.DEFAULT_CHARTER}'; + } + + FlxTween.tween(metadataArtist, {alpha: 1.0}, CHARTER_FADE_DURATION, + { + ease: FlxEase.quartOut, + onComplete: (_) -> { + startArtistTimer(); + } + }); + } + }); + } + + function startArtistTimer():Void + { + charterFadeTween = FlxTween.tween(metadataArtist, {alpha: 0.0}, CHARTER_FADE_DURATION, + { + startDelay: CHARTER_FADE_DELAY, + ease: FlxEase.quartOut, + onComplete: (_) -> { + if (PlayState.instance?.currentChart != null) + { + metadataArtist.text = 'Artist: ${PlayState.instance.currentChart.songArtist}'; + } + else + { + metadataArtist.text = 'Artist: ${Constants.DEFAULT_ARTIST}'; + } + + FlxTween.tween(metadataArtist, {alpha: 1.0}, CHARTER_FADE_DURATION, + { + ease: FlxEase.quartOut, + onComplete: (_) -> { + startCharterTimer(); + } + }); + } + }); + } + /** * Perform additional animations to transition the pause menu in when it is first displayed. */ diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 23d8d2198..5da78e9df 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -120,6 +120,18 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta return DEFAULT_ARTIST; } + /** + * The artist of the song. + */ + public var charter(get, never):String; + + function get_charter():String + { + if (_data != null) return _data?.charter ?? 'Unknown'; + if (_metadata.size() > 0) return _metadata.get(Constants.DEFAULT_VARIATION)?.charter ?? 'Unknown'; + return Constants.DEFAULT_CHARTER; + } + /** * @param id The ID of the song to load. * @param ignoreErrors If false, an exception will be thrown if the song data could not be loaded. @@ -270,6 +282,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta difficulty.songName = metadata.songName; difficulty.songArtist = metadata.artist; + difficulty.charter = metadata.charter ?? Constants.DEFAULT_CHARTER; difficulty.timeFormat = metadata.timeFormat; difficulty.divisions = metadata.divisions; difficulty.timeChanges = metadata.timeChanges; @@ -334,6 +347,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta { difficulty.songName = metadata.songName; difficulty.songArtist = metadata.artist; + difficulty.charter = metadata.charter ?? Constants.DEFAULT_CHARTER; difficulty.timeFormat = metadata.timeFormat; difficulty.divisions = metadata.divisions; difficulty.timeChanges = metadata.timeChanges; @@ -586,6 +600,7 @@ class SongDifficulty public var songName:String = Constants.DEFAULT_SONGNAME; public var songArtist:String = Constants.DEFAULT_ARTIST; + public var charter:String = Constants.DEFAULT_CHARTER; public var timeFormat:SongTimeFormat = Constants.DEFAULT_TIMEFORMAT; public var divisions:Null<Int> = null; public var looped:Bool = false; diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index a313981f4..980f5db4f 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1270,7 +1270,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var result:Null<SongMetadata> = songMetadata.get(selectedVariation); if (result == null) { - result = new SongMetadata('DadBattle', 'Kawai Sprite', selectedVariation); + result = new SongMetadata('Default Song Name', Constants.DEFAULT_ARTIST, selectedVariation); songMetadata.set(selectedVariation, result); } return result; diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx index f85307c64..80a421d80 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx @@ -29,6 +29,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox { var inputSongName:TextField; var inputSongArtist:TextField; + var inputSongCharter:TextField; var inputStage:DropDown; var inputNoteStyle:DropDown; var buttonCharacterPlayer:Button; @@ -89,6 +90,20 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox } }; + inputSongCharter.onChange = function(event:UIEvent) { + var valid:Bool = event.target.text != null && event.target.text != ''; + + if (valid) + { + inputSongCharter.removeClass('invalid-value'); + chartEditorState.currentSongMetadata.charter = event.target.text; + } + else + { + chartEditorState.currentSongMetadata.charter = null; + } + }; + inputStage.onChange = function(event:UIEvent) { var valid:Bool = event.data != null && event.data.id != null; @@ -176,6 +191,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox inputSongName.value = chartEditorState.currentSongMetadata.songName; inputSongArtist.value = chartEditorState.currentSongMetadata.artist; + inputSongCharter.value = chartEditorState.currentSongMetadata.charter; inputStage.value = chartEditorState.currentSongMetadata.playData.stage; inputNoteStyle.value = chartEditorState.currentSongMetadata.playData.noteStyle; inputBPM.value = chartEditorState.currentSongMetadata.timeChanges[0].bpm; diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 2f3b570b3..4e706c612 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -248,6 +248,11 @@ class Constants */ public static final DEFAULT_ARTIST:String = 'Unknown'; + /** + * The default charter for songs. + */ + public static final DEFAULT_CHARTER:String = 'Unknown'; + /** * The default note style for songs. */