From d50ff73d3ce42ec4b4d11d0662402f81c039f1b3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 02:47:21 -0400 Subject: [PATCH 01/26] Registries now get added to the Flixel console (and get lazy instantiated so they don't start before the game does) --- source/funkin/data/BaseRegistry.hx | 7 +++++++ source/funkin/data/dialogue/ConversationRegistry.hx | 9 ++++++++- source/funkin/data/dialogue/DialogueBoxRegistry.hx | 9 ++++++++- source/funkin/data/dialogue/SpeakerRegistry.hx | 9 ++++++++- source/funkin/data/level/LevelRegistry.hx | 9 ++++++++- source/funkin/data/notestyle/NoteStyleRegistry.hx | 9 ++++++++- source/funkin/data/song/SongRegistry.hx | 13 ++++++++++--- source/funkin/data/stage/StageRegistry.hx | 9 ++++++++- 8 files changed, 65 insertions(+), 9 deletions(-) diff --git a/source/funkin/data/BaseRegistry.hx b/source/funkin/data/BaseRegistry.hx index ad028fa94..7419d9425 100644 --- a/source/funkin/data/BaseRegistry.hx +++ b/source/funkin/data/BaseRegistry.hx @@ -55,6 +55,13 @@ abstract class BaseRegistry & Constructible(); this.scriptedEntryIds = []; + + // Lazy initialization of singletons should let this get called, + // but we have this check just in case. + if (FlxG.game != null) + { + FlxG.console.registerObject('registry$registryId', this); + } } /** diff --git a/source/funkin/data/dialogue/ConversationRegistry.hx b/source/funkin/data/dialogue/ConversationRegistry.hx index 9186ef786..4a8af2162 100644 --- a/source/funkin/data/dialogue/ConversationRegistry.hx +++ b/source/funkin/data/dialogue/ConversationRegistry.hx @@ -15,7 +15,14 @@ class ConversationRegistry extends BaseRegistry public static final CONVERSATION_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; - public static final instance:ConversationRegistry = new ConversationRegistry(); + public static var instance(get, never):ConversationRegistry; + static var _instance:Null = null; + + static function get_instance():ConversationRegistry + { + if (_instance == null) _instance = new ConversationRegistry(); + return _instance; + } public function new() { diff --git a/source/funkin/data/dialogue/DialogueBoxRegistry.hx b/source/funkin/data/dialogue/DialogueBoxRegistry.hx index 87205d96c..d07ea6da2 100644 --- a/source/funkin/data/dialogue/DialogueBoxRegistry.hx +++ b/source/funkin/data/dialogue/DialogueBoxRegistry.hx @@ -15,7 +15,14 @@ class DialogueBoxRegistry extends BaseRegistry public static final DIALOGUEBOX_DATA_VERSION_RULE:thx.semver.VersionRule = "1.1.x"; - public static final instance:DialogueBoxRegistry = new DialogueBoxRegistry(); + public static var instance(get, never):DialogueBoxRegistry; + static var _instance:Null = null; + + static function get_instance():DialogueBoxRegistry + { + if (_instance == null) _instance = new DialogueBoxRegistry(); + return _instance; + } public function new() { diff --git a/source/funkin/data/dialogue/SpeakerRegistry.hx b/source/funkin/data/dialogue/SpeakerRegistry.hx index 6bd301dd7..c76c6d766 100644 --- a/source/funkin/data/dialogue/SpeakerRegistry.hx +++ b/source/funkin/data/dialogue/SpeakerRegistry.hx @@ -15,7 +15,14 @@ class SpeakerRegistry extends BaseRegistry public static final SPEAKER_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; - public static final instance:SpeakerRegistry = new SpeakerRegistry(); + public static var instance(get, never):SpeakerRegistry; + static var _instance:Null = null; + + static function get_instance():SpeakerRegistry + { + if (_instance == null) _instance = new SpeakerRegistry(); + return _instance; + } public function new() { diff --git a/source/funkin/data/level/LevelRegistry.hx b/source/funkin/data/level/LevelRegistry.hx index 96712cba5..e37e78d8c 100644 --- a/source/funkin/data/level/LevelRegistry.hx +++ b/source/funkin/data/level/LevelRegistry.hx @@ -15,7 +15,14 @@ class LevelRegistry extends BaseRegistry public static final LEVEL_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; - public static final instance:LevelRegistry = new LevelRegistry(); + public static var instance(get, never):LevelRegistry; + static var _instance:Null = null; + + static function get_instance():LevelRegistry + { + if (_instance == null) _instance = new LevelRegistry(); + return _instance; + } public function new() { diff --git a/source/funkin/data/notestyle/NoteStyleRegistry.hx b/source/funkin/data/notestyle/NoteStyleRegistry.hx index ffb9bf490..5e9fa9a3d 100644 --- a/source/funkin/data/notestyle/NoteStyleRegistry.hx +++ b/source/funkin/data/notestyle/NoteStyleRegistry.hx @@ -15,7 +15,14 @@ class NoteStyleRegistry extends BaseRegistry public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; - public static final instance:NoteStyleRegistry = new NoteStyleRegistry(); + public static var instance(get, never):NoteStyleRegistry; + static var _instance:Null = null; + + static function get_instance():NoteStyleRegistry + { + if (_instance == null) _instance = new NoteStyleRegistry(); + return _instance; + } public function new() { diff --git a/source/funkin/data/song/SongRegistry.hx b/source/funkin/data/song/SongRegistry.hx index e7f74569c..d82e184a5 100644 --- a/source/funkin/data/song/SongRegistry.hx +++ b/source/funkin/data/song/SongRegistry.hx @@ -40,10 +40,17 @@ class SongRegistry extends BaseRegistry } /** - * TODO: What if there was a Singleton macro which created static functions - * that redirected to the instance? + * TODO: What if there was a Singleton macro which automatically created the property for us? */ - public static final instance:SongRegistry = new SongRegistry(); + public static var instance(get, never):SongRegistry; + + static var _instance:Null = null; + + static function get_instance():SongRegistry + { + if (_instance == null) _instance = new SongRegistry(); + return _instance; + } public function new() { diff --git a/source/funkin/data/stage/StageRegistry.hx b/source/funkin/data/stage/StageRegistry.hx index b78292e5b..13a5afb8d 100644 --- a/source/funkin/data/stage/StageRegistry.hx +++ b/source/funkin/data/stage/StageRegistry.hx @@ -15,7 +15,14 @@ class StageRegistry extends BaseRegistry public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; - public static final instance:StageRegistry = new StageRegistry(); + public static var instance(get, never):StageRegistry; + static var _instance:Null = null; + + static function get_instance():StageRegistry + { + if (_instance == null) _instance = new StageRegistry(); + return _instance; + } public function new() { From 4524b66170f1c0391c4a719bce7d090ed0415bc3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 02:47:43 -0400 Subject: [PATCH 02/26] Only show easy/normal/hard in story mode for now --- source/funkin/ui/story/StoryMenuState.hx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 9ce110c73..a5e133725 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -446,7 +446,11 @@ class StoryMenuState extends MusicBeatState */ function changeDifficulty(change:Int = 0):Void { - var difficultyList:Array = currentLevel.getDifficulties(); + // "For now, NO erect in story mode" -Dave + + var difficultyList:Array = Constants.DEFAULT_DIFFICULTY_LIST; + // Use this line to displays all difficulties + // var difficultyList:Array = currentLevel.getDifficulties(); var currentIndex:Int = difficultyList.indexOf(currentDifficultyId); currentIndex += change; From 2b477c9bd1183ba2a35ced7d22233c9c3f2d722e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 02:47:56 -0400 Subject: [PATCH 03/26] Make Conductor a lazy instance --- source/funkin/Conductor.hx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 05c23108f..383a49084 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -36,7 +36,15 @@ class Conductor * You can also do stuff like store a reference to the Conductor and pass it around or temporarily replace it, * or have a second Conductor running at the same time, or other weird stuff like that if you need to. */ - public static var instance:Conductor = new Conductor(); + public static var instance(get, never):Conductor; + + static var _instance:Null = null; + + static function get_instance():Conductor + { + if (_instance == null) _instance = new Conductor(); + return _instance; + } /** * Signal fired when the current Conductor instance advances to a new measure. @@ -505,6 +513,6 @@ class Conductor */ public static function reset():Void { - Conductor.instance = new Conductor(); + _instance = new Conductor(); } } From aea9213eeaca4686acec8f7cd6e5c3e8f4faf95a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 03:04:33 -0400 Subject: [PATCH 04/26] Make sure the BPM label gets updated properly --- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index bdc0d311e..565488da3 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -4949,7 +4949,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState playbarNoteSnap.text = '1/${noteSnapQuant}'; playbarDifficulty.text = '${selectedDifficulty.toTitleCase()}'; - // playbarBPM.text = 'BPM: ${(Conductor.currentTimeChange?.bpm ?? 0.0)}'; + playbarBPM.text = 'BPM: ${(Conductor.instance.bpm ?? 0.0)}'; } function handlePlayhead():Void From c765249030db27e092a4a544c0f614c0ee306a8f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 03:04:52 -0400 Subject: [PATCH 05/26] Complain if the main metadata file specifies a variation (like erect) but the game can't find it. --- source/funkin/play/song/Song.hx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 567c388c7..b0b477ff4 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -139,7 +139,16 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = fetchVariationMetadata(id, vari); - if (variMeta != null) _metadata.set(variMeta.variation, variMeta); + if (variMeta != null) + { + _metadata.set(variMeta.variation, variMeta); + trace(' Loaded variation: $vari'); + } + else + { + FlxG.log.warn('[SONG] Failed to load variation metadata (${id}:${vari}), is the path correct?'); + trace(' FAILED to load variation: $vari'); + } } } From eb5f853e2cf9df81045effd13f70851d8bed6104 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 03:05:18 -0400 Subject: [PATCH 06/26] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 203bb6024..d6f82ec8b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 203bb60249e0a419d473eb6dc1763e62e29ee7fd +Subproject commit d6f82ec8b91823eee809d73e2c4744210a8e7e0b From 28088146eba83d0cb48e91951faf8a8c09d4522d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 22:17:34 -0400 Subject: [PATCH 07/26] Fix bug where Pico dadbattle was playing over normal dadbattle --- assets | 2 +- source/funkin/play/song/Song.hx | 11 ++++++++--- source/funkin/util/Constants.hx | 5 +++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/assets b/assets index 7cbe6ff4e..9a5767d04 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 7cbe6ff4ed7d976e7c69d6677c4aa84988da0e8d +Subproject commit 9a5767d04203a9cb9857608761646bb6a52b1e13 diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 567c388c7..6c4f27420 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -374,12 +374,17 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry):Null { - if (variations == null) possibleVariations = variations; + if (possibleVariations == null) + { + possibleVariations = variations; + possibleVariations.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST)); + } if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0]; - for (variation in variations) + for (variationId in possibleVariations) { - if (difficulties.exists('$diffId-$variation')) return variation; + var variationSuffix = (variationId != Constants.DEFAULT_VARIATION) ? '-$variationId' : ''; + if (difficulties.exists('$diffId$variationSuffix')) return variationId; } return null; diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index c9b99ed46..c7bc03139 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -157,6 +157,11 @@ class Constants */ public static final DEFAULT_VARIATION:String = 'default'; + /** + * Standard variations used by the game. + */ + public static final DEFAULT_VARIATION_LIST:Array = ['default', 'erect', 'pico']; + /** * The default intensity for camera zooms. */ From 471b015d1ad8a4906be231fb3c75151df50a753c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 23:46:03 -0400 Subject: [PATCH 08/26] Add some FlxSignals and showVideo/hideVideo --- source/funkin/play/cutscene/VideoCutscene.hx | 71 ++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index ff56e0919..7e500f05d 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -28,6 +28,31 @@ class VideoCutscene static var vid:FlxVideoSprite; #end + /** + * Called when the video is started. + */ + public static final onVideoStarted:FlxSignal = new FlxSignal(); + + /** + * Called if the video is paused. + */ + public static final onVideoPaused:FlxSignal = new FlxSignal(); + + /** + * Called if the video is resumed. + */ + public static final onVideoResumed:FlxSignal = new FlxSignal(); + + /** + * Called if the video is restarted. onVideoStarted is not called. + */ + public static final onVideoRestarted:FlxSignal = new FlxSignal(); + + /** + * Called when the video is ended or skipped. + */ + public static final onVideoEnded:FlxSignal = new FlxSignal(); + /** * Play a video cutscene. * TODO: Currently this is hardcoded to start the countdown after the video is done. @@ -94,6 +119,8 @@ class VideoCutscene PlayState.instance.add(vid); PlayState.instance.refresh(); + + onVideoStarted.dispatch(); } else { @@ -129,6 +156,8 @@ class VideoCutscene vid.y = 0; // vid.scale.set(0.5, 0.5); }); + + onVideoStarted.dispatch(); } else { @@ -143,6 +172,7 @@ class VideoCutscene if (vid != null) { vid.restartVideo(); + onVideoRestarted.dispatch(); } #end @@ -156,6 +186,8 @@ class VideoCutscene // Resume the video if it was paused. vid.resume(); } + + onVideoRestarted.dispatch(); } #end } @@ -166,6 +198,7 @@ class VideoCutscene if (vid != null) { vid.pauseVideo(); + onVideoPaused.dispatch(); } #end @@ -173,6 +206,41 @@ class VideoCutscene if (vid != null) { vid.pause(); + onVideoPaused.dispatch(); + } + #end + } + + public static function hideVideo():Void + { + #if html5 + if (vid != null) + { + vid.visible = false; + } + #end + + #if hxCodec + if (vid != null) + { + vid.visible = false; + } + #end + } + + public static function showVideo():Void + { + #if html5 + if (vid != null) + { + vid.visible = true; + } + #end + + #if hxCodec + if (vid != null) + { + vid.visible = true; } #end } @@ -183,6 +251,7 @@ class VideoCutscene if (vid != null) { vid.resumeVideo(); + onVideoResumed.dispatch(); } #end @@ -190,6 +259,7 @@ class VideoCutscene if (vid != null) { vid.resume(); + onVideoResumed.dispatch(); } #end } @@ -240,6 +310,7 @@ class VideoCutscene { ease: FlxEase.quadInOut, onComplete: function(twn:FlxTween) { + onVideoEnded.dispatch(); onCutsceneFinish(cutsceneType); } }); From e4a9d25ac01bf65b261076ffad753414967195ef Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 22 Mar 2024 23:53:29 -0400 Subject: [PATCH 09/26] Syntax fix --- source/funkin/play/cutscene/VideoCutscene.hx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 7e500f05d..3da51185f 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -5,6 +5,7 @@ import flixel.FlxSprite; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxColor; +import flixel.util.FlxSignal; import flixel.util.FlxTimer; #if html5 import funkin.graphics.video.FlxVideo; @@ -217,6 +218,7 @@ class VideoCutscene if (vid != null) { vid.visible = false; + blackScreen.visible = false; } #end @@ -224,6 +226,7 @@ class VideoCutscene if (vid != null) { vid.visible = false; + blackScreen.visible = false; } #end } @@ -234,6 +237,7 @@ class VideoCutscene if (vid != null) { vid.visible = true; + blackScreen.visible = false; } #end @@ -241,6 +245,7 @@ class VideoCutscene if (vid != null) { vid.visible = true; + blackScreen.visible = false; } #end } From 8bbb528a9e1326bf01d9a235cadcbc16f0b85b68 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 13:44:27 -0400 Subject: [PATCH 10/26] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 526743915..8b0aa1d56 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 52674391511577300cdb8c08df293ea72099aa82 +Subproject commit 8b0aa1d5633f2f2e7f0eb03498ee71d19cc99564 From 6407770ed6c17b510924fbb019c118608808fb7d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 17:50:48 -0400 Subject: [PATCH 11/26] Rework every class to use FunkinSound. --- source/funkin/audio/FunkinSound.hx | 108 ++++++++++++++++-- source/funkin/audio/SoundGroup.hx | 1 - source/funkin/modding/PolymodHandler.hx | 1 - source/funkin/play/Countdown.hx | 3 +- source/funkin/play/GameOverSubState.hx | 5 +- source/funkin/play/GitarooPause.hx | 6 +- source/funkin/play/PauseSubState.hx | 2 +- source/funkin/play/PlayState.hx | 65 +++++++---- .../funkin/play/components/ComboMilestone.hx | 3 +- .../funkin/play/cutscene/VanillaCutscenes.hx | 3 +- .../play/cutscene/dialogue/Conversation.hx | 36 +++--- source/funkin/ui/Alphabet.hx | 3 +- source/funkin/ui/MenuList.hx | 5 +- source/funkin/ui/MusicBeatState.hx | 3 + source/funkin/ui/debug/DebugMenuSubState.hx | 3 +- .../ui/debug/anim/DebugBoundingState.hx | 3 +- .../ui/debug/charting/ChartEditorState.hx | 7 +- .../handlers/ChartEditorAudioHandler.hx | 4 +- .../funkin/ui/debug/latency/LatencyState.hx | 7 -- .../ui/debug/stage/StageBuilderState.hx | 2 - source/funkin/ui/freeplay/DJBoyfriend.hx | 6 +- source/funkin/ui/freeplay/FreeplayState.hx | 21 +++- source/funkin/ui/mainmenu/MainMenuState.hx | 8 +- source/funkin/ui/options/OptionsState.hx | 4 +- source/funkin/ui/story/StoryMenuState.hx | 12 +- source/funkin/ui/title/AttractState.hx | 6 +- source/funkin/ui/title/TitleState.hx | 16 ++- source/funkin/ui/transition/LoadingState.hx | 10 +- .../funkin/ui/transition/StickerSubState.hx | 5 +- source/funkin/util/MathUtil.hx | 1 + .../funkin/util/plugins/ScreenshotPlugin.hx | 2 +- 31 files changed, 252 insertions(+), 109 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index c64240909..52bd1c7e8 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -8,6 +8,7 @@ import funkin.util.tools.ICloneable; import funkin.data.song.SongData.SongMusicData; import funkin.data.song.SongRegistry; import funkin.audio.waveform.WaveformData; +import openfl.media.SoundMixer; import funkin.audio.waveform.WaveformDataParser; import flixel.math.FlxMath; import openfl.Assets; @@ -18,6 +19,7 @@ import openfl.utils.AssetType; /** * A FlxSound which adds additional functionality: * - Delayed playback via negative song position. + * - Easy functions for immediate playback and recycling. */ @:nullSafety class FunkinSound extends FlxSound implements ICloneable @@ -286,15 +288,27 @@ class FunkinSound extends FlxSound implements ICloneable * Creates a new `FunkinSound` object and loads it as the current music track. * * @param key The key of the music you want to play. Music should be at `music//.ogg`. - * @param overrideExisting Whether to override music if it is already playing. - * @param mapTimeChanges Whether to check for `SongMusicData` to update the Conductor with. + * @param params A set of additional optional parameters. * Data should be at `music//-metadata.json`. */ - public static function playMusic(key:String, overrideExisting:Bool = false, mapTimeChanges:Bool = true):Void + public static function playMusic(key:String, params:FunkinSoundPlayMusicParams):Void { - if (!overrideExisting && FlxG.sound.music?.playing) return; + if (!(params.overrideExisting ?? false) && (FlxG.sound.music?.exists ?? false) && FlxG.sound.music.playing) return; - if (mapTimeChanges) + if (!(params.restartTrack ?? false) && FlxG.sound.music?.playing) + { + if (FlxG.sound.music != null && Std.isOfType(FlxG.sound.music, FunkinSound)) + { + var existingSound:FunkinSound = cast FlxG.sound.music; + // Stop here if we would play a matching music track. + if (existingSound._label == Paths.music('$key/$key')) + { + return; + } + } + } + + if (params?.mapTimeChanges ?? true) { var songMusicData:Null = SongRegistry.instance.parseMusicData(key); // Will fall back and return null if the metadata doesn't exist or can't be parsed. @@ -308,7 +322,14 @@ class FunkinSound extends FlxSound implements ICloneable } } - FlxG.sound.music = FunkinSound.load(Paths.music('$key/$key')); + if (FlxG.sound.music != null) + { + FlxG.sound.music.stop(); + FlxG.sound.music.kill(); + } + + var music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, true, false, true); + if (music != null) FlxG.sound.music = music; // Prevent repeat update() and onFocus() calls. FlxG.sound.list.remove(FlxG.sound.music); @@ -326,11 +347,18 @@ class FunkinSound extends FlxSound implements ICloneable * @param autoPlay Whether to play the sound immediately or wait for a `play()` call. * @param onComplete Called when the sound finished playing. * @param onLoad Called when the sound finished loading. Called immediately for succesfully loaded embedded sounds. - * @return A `FunkinSound` object. + * @return A `FunkinSound` object, or `null` if the sound could not be loaded. */ public static function load(embeddedSound:FlxSoundAsset, volume:Float = 1.0, looped:Bool = false, autoDestroy:Bool = false, autoPlay:Bool = false, - ?onComplete:Void->Void, ?onLoad:Void->Void):FunkinSound + ?onComplete:Void->Void, ?onLoad:Void->Void):Null { + @:privateAccess + if (SoundMixer.__soundChannels.length >= SoundMixer.MAX_ACTIVE_CHANNELS) + { + FlxG.log.error('FunkinSound could not play sound, channels exhausted! Found ${SoundMixer.__soundChannels.length} active sound channels.'); + return null; + } + var sound:FunkinSound = pool.recycle(construct); // Load the sound. @@ -341,6 +369,10 @@ class FunkinSound extends FlxSound implements ICloneable { sound._label = embeddedSound; } + else + { + sound._label = 'unknown'; + } sound.volume = volume; sound.group = FlxG.sound.defaultSoundGroup; @@ -355,6 +387,36 @@ class FunkinSound extends FlxSound implements ICloneable return sound; } + public override function destroy():Void + { + // trace('[FunkinSound] Destroying sound "${this._label}"'); + super.destroy(); + } + + /** + * Play a sound effect once, then destroy it. + * @param key + * @param volume + * @return static function construct():FunkinSound + */ + public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):Void + { + var result = FunkinSound.load(key, volume, false, true, true, onComplete, onLoad); + } + + /** + * Stop all sounds in the pool and allow them to be recycled. + */ + public static function stopAllAudio(musicToo:Bool = false):Void + { + for (sound in pool) + { + if (sound == null) continue; + if (!musicToo && sound == FlxG.sound.music) continue; + sound.destroy(); + } + } + static function construct():FunkinSound { var sound:FunkinSound = new FunkinSound(); @@ -365,3 +427,33 @@ class FunkinSound extends FlxSound implements ICloneable return sound; } } + +/** + * Additional parameters for `FunkinSound.playMusic()` + */ +typedef FunkinSoundPlayMusicParams = +{ + /** + * The volume you want the music to start at. + * @default `1.0` + */ + var ?startingVolume:Float; + + /** + * Whether to override music if a different track is already playing. + * @default `false` + */ + var ?overrideExisting:Bool; + + /** + * Whether to override music if the same track is already playing. + * @default `false` + */ + var ?restartTrack:Bool; + + /** + * Whether to check for `SongMusicData` to update the Conductor with. + * @default `true` + */ + var ?mapTimeChanges:Bool; +} diff --git a/source/funkin/audio/SoundGroup.hx b/source/funkin/audio/SoundGroup.hx index a26537c2a..9a754049b 100644 --- a/source/funkin/audio/SoundGroup.hx +++ b/source/funkin/audio/SoundGroup.hx @@ -1,7 +1,6 @@ package funkin.audio; import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.sound.FlxSound; import funkin.audio.FunkinSound; import flixel.tweens.FlxTween; diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index a88476d4d..78f660d3f 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -209,7 +209,6 @@ class PolymodHandler // Add import aliases for certain classes. // NOTE: Scripted classes are automatically aliased to their parent class. Polymod.addImportAlias('flixel.math.FlxPoint', flixel.math.FlxPoint.FlxBasePoint); - Polymod.addImportAlias('flixel.system.FlxSound', flixel.sound.FlxSound); // Add blacklisting for prohibited classes and packages. // `polymod.*` diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 747565100..10636afdf 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -9,6 +9,7 @@ import funkin.modding.module.ModuleHandler; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import flixel.util.FlxTimer; +import funkin.audio.FunkinSound; class Countdown { @@ -282,7 +283,7 @@ class Countdown if (soundPath == null) return; - FlxG.sound.play(Paths.sound(soundPath), Constants.COUNTDOWN_VOLUME); + FunkinSound.playOnce(Paths.sound(soundPath), Constants.COUNTDOWN_VOLUME); } public static function decrement(step:CountdownStep):CountdownStep diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index ec3282164..a1796e912 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -3,7 +3,6 @@ package funkin.play; import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; -import flixel.sound.FlxSound; import funkin.audio.FunkinSound; import flixel.util.FlxColor; import flixel.util.FlxTimer; @@ -418,7 +417,7 @@ class GameOverSubState extends MusicBeatSubState blueballed = true; if (Assets.exists(Paths.sound('gameplay/gameover/fnf_loss_sfx' + blueBallSuffix))) { - FlxG.sound.play(Paths.sound('gameplay/gameover/fnf_loss_sfx' + blueBallSuffix)); + FunkinSound.playOnce(Paths.sound('gameplay/gameover/fnf_loss_sfx' + blueBallSuffix)); } else { @@ -438,7 +437,7 @@ class GameOverSubState extends MusicBeatSubState if (!Preferences.naughtyness) randomCensor = [1, 3, 8, 13, 17, 21]; - FlxG.sound.play(Paths.sound('jeffGameover/jeffGameover-' + FlxG.random.int(1, 25, randomCensor)), 1, false, null, true, function() { + FunkinSound.playOnce(Paths.sound('jeffGameover/jeffGameover-' + FlxG.random.int(1, 25, randomCensor)), function() { // Once the quote ends, fade in the game over music. if (!isEnding && gameOverMusic != null) { diff --git a/source/funkin/play/GitarooPause.hx b/source/funkin/play/GitarooPause.hx index eae56a9c3..6abe78cd8 100644 --- a/source/funkin/play/GitarooPause.hx +++ b/source/funkin/play/GitarooPause.hx @@ -26,7 +26,11 @@ class GitarooPause extends MusicBeatState override function create():Void { - if (FlxG.sound.music != null) FlxG.sound.music.stop(); + if (FlxG.sound.music != null) + { + FlxG.sound.music.destroy(); + FlxG.sound.music = null; + } var bg:FunkinSprite = FunkinSprite.create('pauseAlt/pauseBG'); add(bg); diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index 03681ce13..f16aa00d8 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -366,7 +366,7 @@ class PauseSubState extends MusicBeatSubState */ function changeSelection(change:Int = 0):Void { - FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); + FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); currentEntry += change; diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 12b290afd..8734d0c1d 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1,20 +1,15 @@ package funkin.play; -import funkin.audio.FunkinSound; import flixel.addons.display.FlxPieDial; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.transition.Transition; -import flixel.addons.transition.Transition; import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxState; -import funkin.graphics.FunkinSprite; import flixel.FlxSubState; -import funkin.graphics.FunkinSprite; import flixel.math.FlxMath; import flixel.math.FlxPoint; import flixel.math.FlxRect; -import funkin.graphics.FunkinSprite; import flixel.text.FlxText; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; @@ -22,18 +17,19 @@ import flixel.ui.FlxBar; import flixel.util.FlxColor; import flixel.util.FlxTimer; import funkin.api.newgrounds.NGio; -import funkin.audio.VoicesGroup; +import funkin.audio.FunkinSound; import funkin.audio.VoicesGroup; import funkin.data.dialogue.ConversationRegistry; import funkin.data.event.SongEventRegistry; import funkin.data.notestyle.NoteStyleData; import funkin.data.notestyle.NoteStyleRegistry; -import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.song.SongData.SongCharacterData; import funkin.data.song.SongData.SongEventData; import funkin.data.song.SongData.SongNoteData; import funkin.data.song.SongRegistry; import funkin.data.stage.StageRegistry; +import funkin.graphics.FunkinCamera; +import funkin.graphics.FunkinSprite; import funkin.Highscore.Tallies; import funkin.input.PreciseInputManager; import funkin.modding.events.ScriptEvent; @@ -44,14 +40,11 @@ import funkin.play.components.ComboMilestone; import funkin.play.components.HealthIcon; import funkin.play.components.PopUpStuff; import funkin.play.cutscene.dialogue.Conversation; -import funkin.play.cutscene.dialogue.Conversation; import funkin.play.cutscene.VanillaCutscenes; import funkin.play.cutscene.VideoCutscene; import funkin.play.notes.NoteDirection; import funkin.play.notes.NoteSplash; import funkin.play.notes.NoteSprite; -import funkin.play.notes.NoteSprite; -import funkin.play.notes.notestyle.NoteStyle; import funkin.play.notes.notestyle.NoteStyle; import funkin.play.notes.Strumline; import funkin.play.notes.SustainTrail; @@ -65,7 +58,6 @@ import funkin.ui.mainmenu.MainMenuState; import funkin.ui.MusicBeatSubState; import funkin.ui.options.PreferencesMenu; import funkin.ui.story.StoryMenuState; -import funkin.graphics.FunkinCamera; import funkin.ui.transition.LoadingState; import funkin.util.SerializerUtil; import haxe.Int64; @@ -1293,16 +1285,35 @@ class PlayState extends MusicBeatSubState currentStage = null; } - // Stop the instrumental. - if (FlxG.sound.music != null) + if (!overrideMusic) { - FlxG.sound.music.stop(); - } + // Stop the instrumental. + if (FlxG.sound.music != null) + { + FlxG.sound.music.destroy(); + FlxG.sound.music = null; + } - // Stop the vocals. - if (vocals != null && vocals.exists) + // Stop the vocals. + if (vocals != null && vocals.exists) + { + vocals.destroy(); + vocals = null; + } + } + else { - vocals.stop(); + // Stop the instrumental. + if (FlxG.sound.music != null) + { + FlxG.sound.music.stop(); + } + + // Stop the vocals. + if (vocals != null && vocals.exists) + { + vocals.stop(); + } } super.debug_refreshModules(); @@ -1899,6 +1910,12 @@ class PlayState extends MusicBeatSubState currentChart.playInst(1.0, false); } + if (FlxG.sound.music == null) + { + FlxG.log.error('PlayState failed to initialize instrumental!'); + return; + } + FlxG.sound.music.onComplete = endSong.bind(false); // A negative instrumental offset means the song skips the first few milliseconds of the track. // This just gets added into the startTimestamp behavior so we don't need to do anything extra. @@ -2428,7 +2445,7 @@ class PlayState extends MusicBeatSubState if (playSound) { vocals.playerVolume = 0; - FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2)); + FunkinSound.playOnce(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.5, 0.6)); } } @@ -2483,7 +2500,7 @@ class PlayState extends MusicBeatSubState if (event.playSound) { vocals.playerVolume = 0; - FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2)); + FunkinSound.playOnce(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2)); } } @@ -2766,7 +2783,11 @@ class PlayState extends MusicBeatSubState if (targetSongId == null) { - FunkinSound.playMusic('freakyMenu'); + FunkinSound.playMusic('freakyMenu', + { + overrideExisting: true, + restartTrack: false + }); // transIn = FlxTransitionableState.defaultTransIn; // transOut = FlxTransitionableState.defaultTransOut; @@ -2844,7 +2865,7 @@ class PlayState extends MusicBeatSubState camHUD.visible = false; isInCutscene = true; - FlxG.sound.play(Paths.sound('Lights_Shut_off'), function() { + FunkinSound.playOnce(Paths.sound('Lights_Shut_off'), function() { // no camFollow so it centers on horror tree var targetSong:Song = SongRegistry.instance.fetchEntry(targetSongId); LoadingState.loadPlayState( diff --git a/source/funkin/play/components/ComboMilestone.hx b/source/funkin/play/components/ComboMilestone.hx index 4119e45c2..22ce2d671 100644 --- a/source/funkin/play/components/ComboMilestone.hx +++ b/source/funkin/play/components/ComboMilestone.hx @@ -4,6 +4,7 @@ import flixel.FlxSprite; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.util.FlxTimer; +import funkin.audio.FunkinSound; class ComboMilestone extends FlxTypedSpriteGroup { @@ -78,7 +79,7 @@ class ComboMilestone extends FlxTypedSpriteGroup function setupCombo(daCombo:Int) { - FlxG.sound.play(Paths.sound('comboSound')); + FunkinSound.playOnce(Paths.sound('comboSound')); wasComboSetup = true; var loopNum:Int = 0; diff --git a/source/funkin/play/cutscene/VanillaCutscenes.hx b/source/funkin/play/cutscene/VanillaCutscenes.hx index a332d0795..7a4349e6a 100644 --- a/source/funkin/play/cutscene/VanillaCutscenes.hx +++ b/source/funkin/play/cutscene/VanillaCutscenes.hx @@ -4,6 +4,7 @@ import flixel.FlxSprite; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxColor; +import funkin.audio.FunkinSound; import flixel.util.FlxTimer; /** @@ -40,7 +41,7 @@ class VanillaCutscenes FlxG.camera.zoom = 2.5; // Play the Sound effect. - FlxG.sound.play(Paths.sound('Lights_Turn_On'), function() { + FunkinSound.playOnce(Paths.sound('Lights_Turn_On'), function() { // Fade in the HUD. trace('SFX done...'); PlayState.instance.camHUD.visible = true; diff --git a/source/funkin/play/cutscene/dialogue/Conversation.hx b/source/funkin/play/cutscene/dialogue/Conversation.hx index f865f3b7b..c520c3e25 100644 --- a/source/funkin/play/cutscene/dialogue/Conversation.hx +++ b/source/funkin/play/cutscene/dialogue/Conversation.hx @@ -1,28 +1,28 @@ package funkin.play.cutscene.dialogue; -import funkin.data.IRegistryEntry; +import flixel.addons.display.FlxPieDial; import flixel.FlxSprite; import flixel.group.FlxSpriteGroup; -import flixel.util.FlxColor; -import funkin.graphics.FunkinSprite; -import flixel.tweens.FlxTween; import flixel.tweens.FlxEase; -import flixel.sound.FlxSound; -import funkin.util.SortUtil; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; import flixel.util.FlxSort; -import funkin.modding.events.ScriptEvent; -import funkin.modding.IScriptedClass.IEventHandler; -import funkin.play.cutscene.dialogue.DialogueBox; -import funkin.modding.IScriptedClass.IDialogueScriptedClass; -import funkin.modding.events.ScriptEventDispatcher; -import flixel.addons.display.FlxPieDial; +import funkin.audio.FunkinSound; import funkin.data.dialogue.ConversationData; import funkin.data.dialogue.ConversationData.DialogueEntryData; import funkin.data.dialogue.ConversationRegistry; -import funkin.data.dialogue.SpeakerData; -import funkin.data.dialogue.SpeakerRegistry; import funkin.data.dialogue.DialogueBoxData; import funkin.data.dialogue.DialogueBoxRegistry; +import funkin.data.dialogue.SpeakerData; +import funkin.data.dialogue.SpeakerRegistry; +import funkin.data.IRegistryEntry; +import funkin.graphics.FunkinSprite; +import funkin.modding.events.ScriptEvent; +import funkin.modding.events.ScriptEventDispatcher; +import funkin.modding.IScriptedClass.IDialogueScriptedClass; +import funkin.modding.IScriptedClass.IEventHandler; +import funkin.play.cutscene.dialogue.DialogueBox; +import funkin.util.SortUtil; /** * A high-level handler for dialogue. @@ -90,7 +90,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl /** * AUDIO */ - var music:FlxSound; + var music:FunkinSound; /** * GRAPHICS @@ -129,8 +129,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl { if (_data.music == null) return; - music = new FlxSound().loadEmbedded(Paths.music(_data.music.asset), true, true); - music.volume = 0; + music = FunkinSound.load(Paths.music(_data.music.asset), 0.0, true, true, true); if (_data.music.fadeTime > 0.0) { @@ -140,9 +139,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl { music.volume = 1.0; } - - FlxG.sound.list.add(music); - music.play(); } public function pauseMusic():Void diff --git a/source/funkin/ui/Alphabet.hx b/source/funkin/ui/Alphabet.hx index 66b95f5b8..e0492bee5 100644 --- a/source/funkin/ui/Alphabet.hx +++ b/source/funkin/ui/Alphabet.hx @@ -5,6 +5,7 @@ import flixel.group.FlxSpriteGroup; import flixel.math.FlxMath; import flixel.util.FlxTimer; import funkin.util.MathUtil; +import funkin.audio.FunkinSound; /** * Loosley based on FlxTypeText lolol @@ -200,7 +201,7 @@ class Alphabet extends FlxSpriteGroup if (FlxG.random.bool(40)) { var daSound:String = "GF_"; - FlxG.sound.play(Paths.soundRandom(daSound, 1, 4)); + FunkinSound.playOnce(Paths.soundRandom(daSound, 1, 4)); } add(letter); diff --git a/source/funkin/ui/MenuList.hx b/source/funkin/ui/MenuList.hx index 3ffe3c330..63a688778 100644 --- a/source/funkin/ui/MenuList.hx +++ b/source/funkin/ui/MenuList.hx @@ -5,6 +5,7 @@ import flixel.effects.FlxFlicker; import flixel.group.FlxGroup; import flixel.math.FlxPoint; import flixel.util.FlxSignal; +import funkin.audio.FunkinSound; class MenuTypedList extends FlxTypedGroup { @@ -93,7 +94,7 @@ class MenuTypedList extends FlxTypedGroup if (newIndex != selectedIndex) { - FlxG.sound.play(Paths.sound('scrollMenu')); + FunkinSound.playOnce(Paths.sound('scrollMenu')); selectItem(newIndex); } @@ -163,7 +164,7 @@ class MenuTypedList extends FlxTypedGroup else { busy = true; - FlxG.sound.play(Paths.sound('confirmMenu')); + FunkinSound.playOnce(Paths.sound('confirmMenu')); FlxFlicker.flicker(selected, 1, 0.06, true, false, function(_) { busy = false; selected.callback(); diff --git a/source/funkin/ui/MusicBeatState.hx b/source/funkin/ui/MusicBeatState.hx index 98197a0e7..2cdc747ef 100644 --- a/source/funkin/ui/MusicBeatState.hx +++ b/source/funkin/ui/MusicBeatState.hx @@ -7,6 +7,7 @@ import flixel.FlxSubState; import flixel.addons.transition.FlxTransitionableState; import flixel.text.FlxText; import flixel.util.FlxColor; +import funkin.audio.FunkinSound; import flixel.util.FlxSort; import funkin.modding.PolymodHandler; import funkin.modding.events.ScriptEvent; @@ -151,6 +152,8 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler } else { + FunkinSound.stopAllAudio(); + onComplete(); } } diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 375fb8f5c..56a05eb86 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -4,6 +4,7 @@ import flixel.math.FlxPoint; import flixel.FlxObject; import flixel.FlxSprite; import funkin.ui.MusicBeatSubState; +import funkin.audio.FunkinSound; import funkin.ui.TextMenuList; import funkin.ui.debug.charting.ChartEditorState; import funkin.ui.MusicBeatSubState; @@ -71,7 +72,7 @@ class DebugMenuSubState extends MusicBeatSubState if (controls.BACK) { - FlxG.sound.play(Paths.sound('cancelMenu')); + FunkinSound.playOnce(Paths.sound('cancelMenu')); exitDebugMenu(); } } diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 46a095a65..86e84117a 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -12,7 +12,6 @@ import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxFrame; import flixel.group.FlxGroup; import flixel.math.FlxPoint; -import flixel.sound.FlxSound; import flixel.text.FlxText; import flixel.util.FlxColor; import funkin.util.MouseUtil; @@ -179,7 +178,7 @@ class DebugBoundingState extends FlxState var objShit = js.html.URL.createObjectURL(swagList.item(0)); trace(objShit); - var funnysound = new FlxSound().loadStream('https://cdn.discordapp.com/attachments/767500676166451231/817821618251759666/Flutter.mp3', false, false, + var funnysound = new FunkinSound().loadStream('https://cdn.discordapp.com/attachments/767500676166451231/817821618251759666/Flutter.mp3', false, false, null, function() { trace('LOADED SHIT??'); }); diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index bdc0d311e..8e82c0fd8 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -15,7 +15,6 @@ import flixel.input.mouse.FlxMouseEvent; import flixel.math.FlxMath; import flixel.math.FlxPoint; import flixel.math.FlxRect; -import flixel.sound.FlxSound; import flixel.system.debug.log.LogStyle; import flixel.system.FlxAssets.FlxSoundAsset; import flixel.text.FlxText; @@ -1091,7 +1090,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState * The chill audio track that plays in the chart editor. * Plays when the main music is NOT being played. */ - var welcomeMusic:FlxSound = new FlxSound(); + var welcomeMusic:FunkinSound = new FunkinSound(); /** * The audio track for the instrumental. @@ -3888,8 +3887,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handleCursor():Void { // Mouse sounds - if (FlxG.mouse.justPressed) FlxG.sound.play(Paths.sound("chartingSounds/ClickDown")); - if (FlxG.mouse.justReleased) FlxG.sound.play(Paths.sound("chartingSounds/ClickUp")); + if (FlxG.mouse.justPressed) FunkinSound.playOnce(Paths.sound("chartingSounds/ClickDown")); + if (FlxG.mouse.justReleased) FunkinSound.playOnce(Paths.sound("chartingSounds/ClickUp")); // Note: If a menu is open in HaxeUI, don't handle cursor behavior. var shouldHandleCursor:Bool = !(isHaxeUIFocused || playbarHeadDragging || isHaxeUIDialogOpen) diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx index 1e1d165f3..26e246371 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx @@ -1,7 +1,6 @@ package funkin.ui.debug.charting.handlers; import flixel.system.FlxAssets.FlxSoundAsset; -import flixel.sound.FlxSound; import funkin.audio.VoicesGroup; import funkin.audio.FunkinSound; import funkin.play.character.BaseCharacter.CharacterType; @@ -302,7 +301,8 @@ class ChartEditorAudioHandler trace('WARN: Failed to play sound $path, asset not found.'); return; } - var snd:FunkinSound = FunkinSound.load(asset); + var snd:Null = FunkinSound.load(asset); + if (snd == null) return; snd.autoDestroy = true; snd.play(true); snd.volume = volume; diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 9ebd29537..bce97b92d 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -242,13 +242,6 @@ class LatencyState extends MusicBeatSubState } } - /* if (FlxG.keys.justPressed.SPACE) - { - FlxG.sound.music.stop(); - - FlxG.resetState(); - }*/ - noteGrp.forEach(function(daNote:NoteSprite) { daNote.y = (strumLine.y - ((Conductor.instance.songPosition - Conductor.instance.instrumentalOffset) - daNote.noteData.time) * 0.45); daNote.x = strumLine.x + 30; diff --git a/source/funkin/ui/debug/stage/StageBuilderState.hx b/source/funkin/ui/debug/stage/StageBuilderState.hx index 074914f58..b556b9fde 100644 --- a/source/funkin/ui/debug/stage/StageBuilderState.hx +++ b/source/funkin/ui/debug/stage/StageBuilderState.hx @@ -37,8 +37,6 @@ class StageBuilderState extends MusicBeatState FlxG.mouse.visible = true; - // var alsoSnd:FlxSound = new FlxSound(); - // snd = new Sound(); // var swagBytes:ByteArray = new ByteArray(8192); diff --git a/source/funkin/ui/freeplay/DJBoyfriend.hx b/source/funkin/ui/freeplay/DJBoyfriend.hx index 55f43d2ef..8cd63dba1 100644 --- a/source/funkin/ui/freeplay/DJBoyfriend.hx +++ b/source/funkin/ui/freeplay/DJBoyfriend.hx @@ -4,8 +4,8 @@ import flixel.FlxSprite; import flixel.util.FlxSignal; import funkin.util.assets.FlxAnimationUtil; import funkin.graphics.adobeanimate.FlxAtlasSprite; -import flixel.sound.FlxSound; import flixel.util.FlxTimer; +import funkin.audio.FunkinSound; import funkin.audio.FlxStreamSound; class DJBoyfriend extends FlxAtlasSprite @@ -178,7 +178,7 @@ class DJBoyfriend extends FlxAtlasSprite if (cartoonSnd == null) { // tv is OFF, but getting turned on - FlxG.sound.play(Paths.sound('tv_on')); + FunkinSound.playOnce(Paths.sound('tv_on')); cartoonSnd = new FlxStreamSound(); FlxG.sound.defaultSoundGroup.add(cartoonSnd); @@ -187,7 +187,7 @@ class DJBoyfriend extends FlxAtlasSprite { // plays it smidge after the click new FlxTimer().start(0.1, function(_) { - FlxG.sound.play(Paths.sound('channel_switch')); + FunkinSound.playOnce(Paths.sound('channel_switch')); }); } // cartoonSnd.loadEmbedded(Paths.sound("cartoons/peck")); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index fc11eec28..9b59663cf 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -174,7 +174,11 @@ class FreeplayState extends MusicBeatSubState isDebug = true; #end - FunkinSound.playMusic('freakyMenu'); + FunkinSound.playMusic('freakyMenu', + { + overrideExisting: true, + restartTrack: false + }); // Add a null entry that represents the RANDOM option songs.push(null); @@ -867,7 +871,7 @@ class FreeplayState extends MusicBeatSubState FlxTimer.globalManager.clear(); dj.onIntroDone.removeAll(); - FlxG.sound.play(Paths.sound('cancelMenu')); + FunkinSound.playOnce(Paths.sound('cancelMenu')); var longestTimer:Float = 0; @@ -1051,7 +1055,7 @@ class FreeplayState extends MusicBeatSubState trace('No songs available!'); busy = false; letterSort.inputEnabled = true; - FlxG.sound.play(Paths.sound('cancelMenu')); + FunkinSound.playOnce(Paths.sound('cancelMenu')); return; } @@ -1084,7 +1088,7 @@ class FreeplayState extends MusicBeatSubState PlayStatePlaylist.campaignId = cap.songData.levelId; // Visual and audio effects. - FlxG.sound.play(Paths.sound('confirmMenu')); + FunkinSound.playOnce(Paths.sound('confirmMenu')); dj.confirm(); new FlxTimer().start(1, function(tmr:FlxTimer) { @@ -1126,7 +1130,7 @@ class FreeplayState extends MusicBeatSubState function changeSelection(change:Int = 0):Void { - FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); + FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); // FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName)); var prevSelected:Int = curSelected; @@ -1178,7 +1182,12 @@ class FreeplayState extends MusicBeatSubState // TODO: Stream the instrumental of the selected song? if (prevSelected == 0) { - FunkinSound.playMusic('freakyMenu'); + FunkinSound.playMusic('freakyMenu', + { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: false + }); FlxG.sound.music.fadeIn(2, 0, 0.8); } } diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index f4d48dba3..a8c2039ab 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -155,7 +155,11 @@ class MainMenuState extends MusicBeatState function playMenuMusic():Void { - FunkinSound.playMusic('freakyMenu'); + FunkinSound.playMusic('freakyMenu', + { + overrideExisting: true, + restartTrack: false + }); } function resetCamStuff() @@ -321,7 +325,7 @@ class MainMenuState extends MusicBeatState if (controls.BACK && menuItems.enabled && !menuItems.busy) { - FlxG.sound.play(Paths.sound('cancelMenu')); + FunkinSound.playOnce(Paths.sound('cancelMenu')); FlxG.switchState(() -> new TitleState()); } } diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index 7b233f03d..0f33a0780 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -5,9 +5,11 @@ import flixel.FlxSubState; import flixel.addons.transition.FlxTransitionableState; import flixel.group.FlxGroup; import flixel.util.FlxSignal; +import funkin.audio.FunkinSound; import funkin.ui.mainmenu.MainMenuState; import funkin.ui.MusicBeatState; import funkin.util.WindowUtil; +import funkin.audio.FunkinSound; import funkin.input.Controls; class OptionsState extends MusicBeatState @@ -143,7 +145,7 @@ class Page extends FlxGroup { if (canExit && controls.BACK) { - FlxG.sound.play(Paths.sound('cancelMenu')); + FunkinSound.playOnce(Paths.sound('cancelMenu')); exit(); } } diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 9ce110c73..315444fb0 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -231,7 +231,11 @@ class StoryMenuState extends MusicBeatState function playMenuMusic():Void { - FunkinSound.playMusic('freakyMenu'); + FunkinSound.playMusic('freakyMenu', + { + overrideExisting: true, + restartTrack: false + }); } function updateData():Void @@ -382,7 +386,7 @@ class StoryMenuState extends MusicBeatState if (controls.BACK && !exitingMenu && !selectedLevel) { - FlxG.sound.play(Paths.sound('cancelMenu')); + FunkinSound.playOnce(Paths.sound('cancelMenu')); exitingMenu = true; FlxG.switchState(() -> new MainMenuState()); } @@ -511,7 +515,7 @@ class StoryMenuState extends MusicBeatState { if (!currentLevel.isUnlocked()) { - FlxG.sound.play(Paths.sound('cancelMenu')); + FunkinSound.playOnce(Paths.sound('cancelMenu')); return; } @@ -519,7 +523,7 @@ class StoryMenuState extends MusicBeatState selectedLevel = true; - FlxG.sound.play(Paths.sound('confirmMenu')); + FunkinSound.playOnce(Paths.sound('confirmMenu')); currentLevelTitle.isFlashing = true; diff --git a/source/funkin/ui/title/AttractState.hx b/source/funkin/ui/title/AttractState.hx index 63a9e63ad..0af97afd9 100644 --- a/source/funkin/ui/title/AttractState.hx +++ b/source/funkin/ui/title/AttractState.hx @@ -22,7 +22,11 @@ class AttractState extends MusicBeatState public override function create():Void { // Pause existing music. - FlxG.sound.music.stop(); + if (FlxG.sound.music != null) + { + FlxG.sound.music.destroy(); + FlxG.sound.music = null; + } #if html5 playVideoHTML5(ATTRACT_VIDEO_PATH); diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 5cc7b8cc1..0a32b5890 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -222,10 +222,14 @@ class TitleState extends MusicBeatState { var shouldFadeIn = (FlxG.sound.music == null); // Load music. Includes logic to handle BPM changes. - FunkinSound.playMusic('freakyMenu', false, true); - FlxG.sound.music.volume = 0; + FunkinSound.playMusic('freakyMenu', + { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: true + }); // Fade from 0.0 to 0.7 over 4 seconds - if (shouldFadeIn) FlxG.sound.music.fadeIn(4, 0, 0.7); + if (shouldFadeIn) FlxG.sound.music.fadeIn(4.0, 0.0, 0.7); } function getIntroTextShit():Array> @@ -323,7 +327,7 @@ class TitleState extends MusicBeatState if (Date.now().getDay() == 5) NGio.unlockMedal(61034); titleText.animation.play('press'); FlxG.camera.flash(FlxColor.WHITE, 1); - FlxG.sound.play(Paths.sound('confirmMenu'), 0.7); + FunkinSound.playOnce(Paths.sound('confirmMenu'), 0.7); transitioning = true; var targetState:NextState = () -> new MainMenuState(); @@ -338,7 +342,7 @@ class TitleState extends MusicBeatState // ngSpr?? FlxG.switchState(targetState); }); - // FlxG.sound.play(Paths.music('titleShoot'), 0.7); + // FunkinSound.playOnce(Paths.music('titleShoot'), 0.7); } if (pressedEnter && !skippedIntro && initialized) skipIntro(); @@ -392,7 +396,7 @@ class TitleState extends MusicBeatState Conductor.instance.forceBPM(190); FlxG.camera.flash(FlxColor.WHITE, 1); - FlxG.sound.play(Paths.sound('confirmMenu'), 0.7); + FunkinSound.playOnce(Paths.sound('confirmMenu'), 0.7); } function createCoolText(textArray:Array) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 23b3db6a9..980c264e3 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -171,7 +171,12 @@ class LoadingState extends MusicBeatState function onLoad():Void { - if (stopMusic && FlxG.sound.music != null) FlxG.sound.music.stop(); + // Stop the instrumental. + if (stopMusic && FlxG.sound.music != null) + { + FlxG.sound.music.destroy(); + FlxG.sound.music = null; + } FlxG.switchState(target); } @@ -200,7 +205,8 @@ class LoadingState extends MusicBeatState // All assets preloaded, switch directly to play state (defualt on other targets). if (shouldStopMusic && FlxG.sound.music != null) { - FlxG.sound.music.stop(); + FlxG.sound.music.destroy(); + FlxG.sound.music = null; } // Load and cache the song's charts. diff --git a/source/funkin/ui/transition/StickerSubState.hx b/source/funkin/ui/transition/StickerSubState.hx index 981a30e09..0b5e16f97 100644 --- a/source/funkin/ui/transition/StickerSubState.hx +++ b/source/funkin/ui/transition/StickerSubState.hx @@ -18,6 +18,7 @@ import flixel.addons.transition.FlxTransitionableState; import openfl.display.BitmapData; import funkin.ui.freeplay.FreeplayState; import openfl.geom.Matrix; +import funkin.audio.FunkinSound; import openfl.display.Sprite; import openfl.display.Bitmap; import flixel.FlxState; @@ -137,7 +138,7 @@ 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)); + FunkinSound.playOnce(Paths.sound(daSound)); if (grpStickers == null || ind == grpStickers.members.length - 1) { @@ -227,7 +228,7 @@ class StickerSubState extends MusicBeatSubState sticker.visible = true; var daSound:String = FlxG.random.getObject(sounds); - FlxG.sound.play(Paths.sound(daSound)); + FunkinSound.playOnce(Paths.sound(daSound)); var frameTimer:Int = FlxG.random.int(0, 2); diff --git a/source/funkin/util/MathUtil.hx b/source/funkin/util/MathUtil.hx index 532e92f15..5db8f8d76 100644 --- a/source/funkin/util/MathUtil.hx +++ b/source/funkin/util/MathUtil.hx @@ -19,6 +19,7 @@ class MathUtil * * @return The interpolated value. */ + @:deprecated('Use smoothLerp instead') public static function coolLerp(base:Float, target:Float, ratio:Float):Float { return base + cameraLerp(ratio) * (target - base); diff --git a/source/funkin/util/plugins/ScreenshotPlugin.hx b/source/funkin/util/plugins/ScreenshotPlugin.hx index d7e8109b8..9ac21d4b8 100644 --- a/source/funkin/util/plugins/ScreenshotPlugin.hx +++ b/source/funkin/util/plugins/ScreenshotPlugin.hx @@ -174,7 +174,7 @@ class ScreenshotPlugin extends FlxBasic FlxTween.tween(flashSpr, {alpha: 0}, 0.15, {ease: FlxEase.quadOut, onComplete: _ -> FlxG.stage.removeChild(flashSpr)}); // Play a sound (auto-play is true). - FunkinSound.load(Paths.sound('screenshot'), 1.0, false, true, true); + FunkinSound.playOnce(Paths.sound('screenshot'), 1.0); } static final PREVIEW_INITIAL_DELAY = 0.25; // How long before the preview starts fading in. From ecea5e89e2377d5dc01e97fde91098f0033fcbc1 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 17:51:19 -0400 Subject: [PATCH 12/26] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 526743915..024ade791 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 52674391511577300cdb8c08df293ea72099aa82 +Subproject commit 024ade791ffc39afcf8b075841b19ca0f67b00d5 From 709fbc859443f753b548f23760758d69b734101c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 18:11:06 -0400 Subject: [PATCH 13/26] Fix a bug where lag could cause the opponent to miss. --- source/funkin/play/PlayState.hx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 12b290afd..f7bf6fc22 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2089,8 +2089,7 @@ class PlayState extends MusicBeatSubState holdNote.handledMiss = true; // We dropped a hold note. - // Mute vocals and play miss animation, but don't penalize. - vocals.opponentVolume = 0; + // Play miss animation, but don't penalize. currentStage.getOpponent().playSingAnimation(holdNote.noteData.getDirection(), true); } } From a8486a47dfd879e3370f804900cb61ee811b7675 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 18:22:15 -0400 Subject: [PATCH 14/26] Fix a bug where the album disappears never to return --- source/funkin/ui/freeplay/FreeplayState.hx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index fc11eec28..4e0d7ccf3 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1013,7 +1013,14 @@ class FreeplayState extends MusicBeatSubState // Set the difficulty star count on the right. albumRoll.setDifficultyStars(daSong?.songRating); - albumRoll.albumId = daSong?.albumId ?? Constants.DEFAULT_ALBUM_ID; + + // Set the album graphic and play the animation if relevant. + var newAlbumId:String = daSong?.albumId ?? Constants.DEFAULT_ALBUM_ID; + if (albumRoll.albumId != newAlbumId) + { + albumRoll.albumId = newAlbumId; + albumRoll.playIntro(); + } } // Clears the cache of songs, frees up memory, they' ll have to be loaded in later tho function clearDaCache(actualSongTho:String) From 24b03e4f6bfe9f6d0dcf32195b4c0a44f434ea52 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 23:38:07 -0400 Subject: [PATCH 15/26] Replace calls to FlxG.sound.playMusic with ones that set the BPM. --- assets | 2 +- source/funkin/audio/FunkinSound.hx | 30 ++++++++++++++----- source/funkin/play/ResultState.hx | 20 +++++++++---- .../funkin/ui/debug/latency/LatencyState.hx | 2 -- source/funkin/ui/freeplay/FreeplayState.hx | 22 ++++++++------ source/funkin/ui/title/TitleState.hx | 2 -- 6 files changed, 51 insertions(+), 27 deletions(-) diff --git a/assets b/assets index 024ade791..3e8bea70e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 024ade791ffc39afcf8b075841b19ca0f67b00d5 +Subproject commit 3e8bea70e7dcc76df67a0e87b85ef28ed5140371 diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 52bd1c7e8..687860265 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -290,10 +290,11 @@ class FunkinSound extends FlxSound implements ICloneable * @param key The key of the music you want to play. Music should be at `music//.ogg`. * @param params A set of additional optional parameters. * Data should be at `music//-metadata.json`. + * @return Whether the music was started. `false` if music was already playing or could not be started */ - public static function playMusic(key:String, params:FunkinSoundPlayMusicParams):Void + public static function playMusic(key:String, params:FunkinSoundPlayMusicParams):Bool { - if (!(params.overrideExisting ?? false) && (FlxG.sound.music?.exists ?? false) && FlxG.sound.music.playing) return; + if (!(params.overrideExisting ?? false) && (FlxG.sound.music?.exists ?? false) && FlxG.sound.music.playing) return false; if (!(params.restartTrack ?? false) && FlxG.sound.music?.playing) { @@ -303,7 +304,7 @@ class FunkinSound extends FlxSound implements ICloneable // Stop here if we would play a matching music track. if (existingSound._label == Paths.music('$key/$key')) { - return; + return false; } } } @@ -328,11 +329,20 @@ class FunkinSound extends FlxSound implements ICloneable FlxG.sound.music.kill(); } - var music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, true, false, true); - if (music != null) FlxG.sound.music = music; + var music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, params.loop ?? true, false, true); + if (music != null) + { + FlxG.sound.music = music; - // Prevent repeat update() and onFocus() calls. - FlxG.sound.list.remove(FlxG.sound.music); + // Prevent repeat update() and onFocus() calls. + FlxG.sound.list.remove(FlxG.sound.music); + + return true; + } + else + { + return false; + } } /** @@ -451,6 +461,12 @@ typedef FunkinSoundPlayMusicParams = */ var ?restartTrack:Bool; + /** + * Whether the music should loop or play once. + * @default `true` + */ + var ?loop:Bool; + /** * Whether to check for `SongMusicData` to update the Conductor with. * @default `true` diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index a78d61583..c695b1db4 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -13,6 +13,7 @@ import flixel.text.FlxBitmapText; import flixel.tweens.FlxEase; import funkin.ui.freeplay.FreeplayState; import flixel.tweens.FlxTween; +import funkin.audio.FunkinSound; import flixel.util.FlxGradient; import flixel.util.FlxTimer; import funkin.graphics.shaders.LeftMaskShader; @@ -48,9 +49,13 @@ class ResultState extends MusicBeatSubState else resultsVariation = NORMAL; - var loops:Bool = resultsVariation != SHIT; - - FlxG.sound.playMusic(Paths.music("results" + resultsVariation), 1, loops); + FunkinSound.playMusic('results$resultsVariation', + { + startingVolume: 1.0, + overrideExisting: true, + restartTrack: true, + loop: resultsVariation != SHIT + }); // TEMP-ish, just used to sorta "cache" the 3000x3000 image! var cacheBullShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/soundSystem")); @@ -348,9 +353,12 @@ class ResultState extends MusicBeatSubState if (controls.PAUSE) { FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8); - FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1, {onComplete: _ -> { - FlxTween.tween(FlxG.sound.music, {pitch: 0.5}, 0.4); - }}); + FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1, + { + onComplete: _ -> { + FlxTween.tween(FlxG.sound.music, {pitch: 0.5}, 0.4); + } + }); if (params.storyMode) { openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker))); diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index bce97b92d..7b2eabb1c 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -71,8 +71,6 @@ class LatencyState extends MusicBeatSubState // trace("EVENT LISTENER: " + key); }); - // FlxG.sound.playMusic(Paths.sound('soundTest')); - // funnyStatsGraph.hi Conductor.instance.forceBPM(60); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 9b59663cf..249c7ffae 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1131,7 +1131,6 @@ class FreeplayState extends MusicBeatSubState function changeSelection(change:Int = 0):Void { FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); - // FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName)); var prevSelected:Int = curSelected; @@ -1174,20 +1173,25 @@ class FreeplayState extends MusicBeatSubState { if (curSelected == 0) { - FlxG.sound.playMusic(Paths.music('freeplay/freeplayRandom'), 0); + FunkinSound.playMusic('freeplayRandom', + { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: true + }); FlxG.sound.music.fadeIn(2, 0, 0.8); } else { // TODO: Stream the instrumental of the selected song? - if (prevSelected == 0) + var didReplace:Bool = FunkinSound.playMusic('freakyMenu', + { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: false + }); + if (didReplace) { - FunkinSound.playMusic('freakyMenu', - { - startingVolume: 0.0, - overrideExisting: true, - restartTrack: false - }); FlxG.sound.music.fadeIn(2, 0, 0.8); } } diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 0a32b5890..1a4e13ab1 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -389,8 +389,6 @@ class TitleState extends MusicBeatState { cheatActive = true; - FlxG.sound.playMusic(Paths.music('tutorialTitle'), 1); - var spec:SpectogramSprite = new SpectogramSprite(FlxG.sound.music); add(spec); From 138dfd61e8a42e2fe1c1d7c217346e5632c8f687 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 23:52:08 -0400 Subject: [PATCH 16/26] Fix a bug where the Camera Zoom toggle didn't work. --- source/funkin/play/PlayState.hx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 12b290afd..6c3d790d7 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1353,7 +1353,10 @@ class PlayState extends MusicBeatSubState } // Only zoom camera if we are zoomed by less than 35%. - if (FlxG.camera.zoom < (1.35 * defaultCameraZoom) && cameraZoomRate > 0 && Conductor.instance.currentBeat % cameraZoomRate == 0) + if (Preferences.zoomCamera + && FlxG.camera.zoom < (1.35 * defaultCameraZoom) + && cameraZoomRate > 0 + && Conductor.instance.currentBeat % cameraZoomRate == 0) { // Zoom camera in (1.5%) currentCameraZoom += cameraZoomIntensity * defaultCameraZoom; From 2b1fc1e7d722bf5e5663c432c35b4697a389e149 Mon Sep 17 00:00:00 2001 From: Hazel Date: Mon, 25 Mar 2024 16:12:37 +0100 Subject: [PATCH 17/26] bugfix: html5 builds (#418) --- .github/workflows/build-shit.yml | 6 ++++-- assets | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-shit.yml b/.github/workflows/build-shit.yml index 49bab1ac1..e217d1f18 100644 --- a/.github/workflows/build-shit.yml +++ b/.github/workflows/build-shit.yml @@ -13,8 +13,9 @@ jobs: apt update apt install -y sudo git curl unzip - name: Fix git config on posix runner + # this can't be {{ github.workspace }} because that's not docker-aware run: | - git config --global --add safe.directory ${{ github.workspace }} + git config --global --add safe.directory $GITHUB_WORKSPACE - name: Get checkout token uses: actions/create-github-app-token@v1 id: app_token @@ -90,8 +91,9 @@ jobs: runs-on: [self-hosted, macos] steps: - name: Fix git config on posix runner + # this can't be {{ github.workspace }} because that's not docker-aware run: | - git config --global --add safe.directory ${{ github.workspace }} + git config --global --add safe.directory $GITHUB_WORKSPACE - name: Get checkout token uses: actions/create-github-app-token@v1 id: app_token diff --git a/assets b/assets index 8b0aa1d56..526743915 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8b0aa1d5633f2f2e7f0eb03498ee71d19cc99564 +Subproject commit 52674391511577300cdb8c08df293ea72099aa82 From 275a58e633f18b05320b41441789d58b5b1f4a9a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 25 Mar 2024 13:42:35 -0400 Subject: [PATCH 18/26] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 9a5767d04..3b6008899 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 9a5767d04203a9cb9857608761646bb6a52b1e13 +Subproject commit 3b6008899aefa1fe952c1cc5ebf9506464a86d3c From 6a5026b7146ce1e7b1986b606662e6e4388e8202 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 25 Mar 2024 15:06:47 -0400 Subject: [PATCH 19/26] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 3e8bea70e..3b6008899 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3e8bea70e7dcc76df67a0e87b85ef28ed5140371 +Subproject commit 3b6008899aefa1fe952c1cc5ebf9506464a86d3c From a66b746e4393220b03acf53e38a2a7990eac8653 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 25 Mar 2024 16:01:38 -0400 Subject: [PATCH 20/26] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d6f82ec8b..8bb6214e1 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d6f82ec8b91823eee809d73e2c4744210a8e7e0b +Subproject commit 8bb6214e16c823b8b5a522a39b7a7e01d6283abf From 07ad25006008910a4c8c9a706b64267cfbca306f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 25 Mar 2024 21:08:39 -0400 Subject: [PATCH 21/26] Fix an audio crash when exiting a cutscene --- source/funkin/play/PlayState.hx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a8cb879a3..169809a63 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2941,7 +2941,10 @@ class PlayState extends MusicBeatSubState if (overrideMusic) { // Stop the music. Do NOT destroy it, something still references it! - FlxG.sound.music.pause(); + if (FlxG.sound.music != null) + { + FlxG.sound.music.pause(); + } if (vocals != null) { vocals.pause(); @@ -2951,7 +2954,10 @@ class PlayState extends MusicBeatSubState else { // Stop and destroy the music. - FlxG.sound.music.pause(); + if (FlxG.sound.music != null) + { + FlxG.sound.music.pause(); + } if (vocals != null) { vocals.destroy(); From f4617cbbda6cb3b62ea7a7bdf351d8d3f366d533 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 25 Mar 2024 21:08:53 -0400 Subject: [PATCH 22/26] Add mac builds with proper arguments --- .vscode/settings.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 84af3a3fd..13a1862d2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -204,6 +204,21 @@ "label": "HTML5 / Debug (Watch)", "target": "html5", "args": ["-debug", "-watch", "-DFORCE_DEBUG_VERSION"] + }, + { + "label": "macOS / Debug", + "target": "mac", + "args": ["-debug", "-DFORCE_DEBUG_VERSION"] + }, + { + "label": "macOS / Release", + "target": "mac", + "args": ["-release"] + }, + { + "label": "macOS / Release (GitHub Actions)", + "target": "mac", + "args": ["-release", "-DGITHUB_BUILD"] } ], "cmake.configureOnOpen": false, From 90f861628d6869b9b148782ed0ce1c5bf8f66ccc Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 25 Mar 2024 21:09:02 -0400 Subject: [PATCH 23/26] Fix an HTML5 build issue. --- .../ui/debug/anim/DebugBoundingState.hx | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 86e84117a..1aa5d6e12 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -1,31 +1,35 @@ package funkin.ui.debug.anim; -import funkin.util.SerializerUtil; -import funkin.play.character.CharacterData; -import flixel.FlxCamera; -import flixel.FlxSprite; -import flixel.FlxState; import flixel.addons.display.FlxGridOverlay; import flixel.addons.ui.FlxInputText; import flixel.addons.ui.FlxUIDropDownMenu; +import flixel.FlxCamera; +import flixel.FlxSprite; +import flixel.FlxState; import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxFrame; import flixel.group.FlxGroup; import flixel.math.FlxPoint; import flixel.text.FlxText; import flixel.util.FlxColor; -import funkin.util.MouseUtil; import flixel.util.FlxSpriteUtil; import flixel.util.FlxTimer; +import funkin.audio.FunkinSound; +import funkin.input.Cursor; import funkin.play.character.BaseCharacter; +import funkin.play.character.CharacterData; import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.character.SparrowCharacter; -import haxe.ui.RuntimeComponentBuilder; +import funkin.ui.mainmenu.MainMenuState; +import funkin.util.MouseUtil; +import funkin.util.SerializerUtil; +import funkin.util.SortUtil; import haxe.ui.components.DropDown; import haxe.ui.core.Component; +import haxe.ui.core.Screen; import haxe.ui.events.ItemEvent; import haxe.ui.events.UIEvent; -import funkin.ui.mainmenu.MainMenuState; +import haxe.ui.RuntimeComponentBuilder; import lime.utils.Assets as LimeAssets; import openfl.Assets; import openfl.events.Event; @@ -33,13 +37,8 @@ import openfl.events.IOErrorEvent; import openfl.geom.Rectangle; import openfl.net.FileReference; import openfl.net.URLLoader; -import funkin.ui.mainmenu.MainMenuState; import openfl.net.URLRequest; import openfl.utils.ByteArray; -import funkin.input.Cursor; -import funkin.play.character.CharacterData.CharacterDataParser; -import funkin.util.SortUtil; -import haxe.ui.core.Screen; using flixel.util.FlxSpriteUtil; From 5ae075e947c1fdbdd50614f0750f02f5b3f47fc2 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 25 Mar 2024 21:09:14 -0400 Subject: [PATCH 24/26] Fix a couple Flixel warnings on the results screen. --- source/funkin/play/ResultState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index c695b1db4..821f4ba3c 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -109,7 +109,7 @@ class ResultState extends MusicBeatSubState add(gf); var boyfriend:FlxSprite = FunkinSprite.createSparrow(640, -200, 'resultScreen/resultBoyfriendGOOD'); - boyfriend.animation.addByPrefix("fall", "Boyfriend Good", 24, false); + boyfriend.animation.addByPrefix("fall", "Boyfriend Good Anim0", 24, false); boyfriend.visible = false; boyfriend.animation.finishCallback = function(_) { boyfriend.animation.play('fall', true, false, 14); @@ -164,7 +164,7 @@ class ResultState extends MusicBeatSubState add(blackTopBar); var resultsAnim:FunkinSprite = FunkinSprite.createSparrow(-200, -10, "resultScreen/results"); - resultsAnim.animation.addByPrefix("result", "results", 24, false); + resultsAnim.animation.addByPrefix("result", "results instance 1", 24, false); resultsAnim.animation.play("result"); add(resultsAnim); From 368b82846ec0d2b46cf1d9466de7e19aa7eff2f7 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 25 Mar 2024 21:15:20 -0400 Subject: [PATCH 25/26] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 3b6008899..9d2bfff5b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3b6008899aefa1fe952c1cc5ebf9506464a86d3c +Subproject commit 9d2bfff5b595f6c0b1c3d7228d7cad7430694f57 From 364652a22f8878b3fa87503ce372b2ab7f2ca039 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 26 Mar 2024 01:28:58 -0400 Subject: [PATCH 26/26] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 9d2bfff5b..366aab684 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 9d2bfff5b595f6c0b1c3d7228d7cad7430694f57 +Subproject commit 366aab68406311782e1c1c7a5e9de0a224ccf6fd