diff --git a/source/flixel/tweens/misc/BackgroundColorTween.hx b/source/flixel/tweens/misc/BackgroundColorTween.hx deleted file mode 100644 index b8b2d993f..000000000 --- a/source/flixel/tweens/misc/BackgroundColorTween.hx +++ /dev/null @@ -1,66 +0,0 @@ -package flixel.tweens.misc; - -/** - * Tweens the background color of a state. - * Tweens the red, green, blue, and/or alpha values of the color. - * - * @see `flixel.tweens.misc.ColorTween` for something that operates on sprites! - */ -class BackgroundColorTween extends FlxTween -{ - public var color(default, null):FlxColor; - - var startColor:FlxColor; - var endColor:FlxColor; - - /** - * State object whose color to tween - */ - public var targetState(default, null):FlxState; - - /** - * Clean up references - */ - override public function destroy() - { - super.destroy(); - targetState = null; - } - - /** - * Tweens the color to a new color and an alpha to a new alpha. - * - * @param duration Duration of the tween. - * @param fromColor Start color. - * @param toColor End color. - * @param targetState Optional sprite object whose color to tween. - * @return The tween for chaining. - */ - public function tween(duration:Float, fromColor:FlxColor, toColor:FlxColor, ?targetState:FlxSprite):ColorTween - { - this.color = startColor = fromColor; - this.endColor = toColor; - this.duration = duration; - this.targetState = targetState; - this.start(); - return this; - } - - override function update(elapsed:Float):Void - { - super.update(elapsed); - color = FlxColor.interpolate(startColor, endColor, scale); - - if (targetState != null) - { - targetState.bgColor = color; - // Alpha should apply inherently. - // targetState.alpha = color.alphaFloat; - } - } - - override function isTweenOf(object:Dynamic, ?field:String):Bool - { - return targetState == object && (field == null || field == "color"); - } -} diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 0a59fb70b..b08710c33 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -203,6 +203,9 @@ class InitState extends FlxState // Plugins provide a useful interface for globally active Flixel objects, // that receive update events regardless of the current state. // TODO: Move scripted Module behavior to a Flixel plugin. + #if debug + funkin.util.plugins.MemoryGCPlugin.initialize(); + #end funkin.util.plugins.EvacuateDebugPlugin.initialize(); funkin.util.plugins.ForceCrashPlugin.initialize(); funkin.util.plugins.ReloadAssetsDebugPlugin.initialize(); diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index e7ce68d08..704407c14 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -25,6 +25,9 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound> { static final MAX_VOLUME:Float = 2.0; + /** + * Using `FunkinSound.load` will override a dead instance from here rather than creating a new one, if possible! + */ static var cache(default, null):FlxTypedGroup<FunkinSound> = new FlxTypedGroup<FunkinSound>(); public var muted(default, set):Bool = false; @@ -264,6 +267,8 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound> { var sound:FunkinSound = cache.recycle(construct); + // Load the sound. + // Sets `exists = true` as a side effect. sound.loadEmbedded(embeddedSound, looped, autoDestroy, onComplete); if (embeddedSound is String) diff --git a/source/funkin/audio/SoundGroup.hx b/source/funkin/audio/SoundGroup.hx index 0e81a0901..a26537c2a 100644 --- a/source/funkin/audio/SoundGroup.hx +++ b/source/funkin/audio/SoundGroup.hx @@ -80,8 +80,9 @@ class SoundGroup extends FlxTypedGroup<FunkinSound> // We have to play, then pause the sound to set the time, // else the sound will restart immediately when played. - result.play(true, 0.0); - result.pause(); + // TODO: Past me experienced that issue but present me didn't? Investigate. + // result.play(true, 0.0); + // result.pause(); result.time = this.time; result.onComplete = function() { diff --git a/source/funkin/graphics/video/FlxVideo.hx b/source/funkin/graphics/video/FlxVideo.hx index e95d7caa6..66829af00 100644 --- a/source/funkin/graphics/video/FlxVideo.hx +++ b/source/funkin/graphics/video/FlxVideo.hx @@ -40,6 +40,15 @@ class FlxVideo extends FlxBasic netStream.play(videoPath); } + public function restartVideo():Void + { + // Seek to the beginning of the video. + if (netStream != null) + { + netStream.seek(0); + } + } + public function finishVideo():Void { netStream.dispose(); diff --git a/source/funkin/import.hx b/source/funkin/import.hx index 23b588044..02055d4ed 100644 --- a/source/funkin/import.hx +++ b/source/funkin/import.hx @@ -15,7 +15,6 @@ using funkin.util.tools.ArraySortTools; using funkin.util.tools.ArrayTools; using funkin.util.tools.DynamicTools; using funkin.util.tools.FloatTools; -using funkin.util.tools.FlxTweenTools; using funkin.util.tools.Int64Tools; using funkin.util.tools.IntTools; using funkin.util.tools.IteratorTools; diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index c4760cf5f..0857678d0 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -58,12 +58,11 @@ class Controls extends FlxActionSet var _back = new FlxActionDigital(Action.BACK); var _pause = new FlxActionDigital(Action.PAUSE); var _reset = new FlxActionDigital(Action.RESET); + var _screenshot = new FlxActionDigital(Action.SCREENSHOT); var _cutscene_advance = new FlxActionDigital(Action.CUTSCENE_ADVANCE); - var _cutscene_skip = new FlxActionDigital(Action.CUTSCENE_SKIP); var _debug_menu = new FlxActionDigital(Action.DEBUG_MENU); var _debug_chart = new FlxActionDigital(Action.DEBUG_CHART); var _debug_stage = new FlxActionDigital(Action.DEBUG_STAGE); - var _screenshot = new FlxActionDigital(Action.SCREENSHOT); var _volume_up = new FlxActionDigital(Action.VOLUME_UP); var _volume_down = new FlxActionDigital(Action.VOLUME_DOWN); var _volume_mute = new FlxActionDigital(Action.VOLUME_MUTE); @@ -208,16 +207,21 @@ class Controls extends FlxActionSet inline function get_PAUSE() return _pause.check(); + public var RESET(get, never):Bool; + + inline function get_RESET() + return _reset.check(); + + public var SCREENSHOT(get, never):Bool; + + inline function get_SCREENSHOT() + return _screenshot.check(); + public var CUTSCENE_ADVANCE(get, never):Bool; inline function get_CUTSCENE_ADVANCE() return _cutscene_advance.check(); - public var CUTSCENE_SKIP(get, never):Bool; - - inline function get_CUTSCENE_SKIP() - return _cutscene_skip.check(); - public var DEBUG_MENU(get, never):Bool; inline function get_DEBUG_MENU() @@ -233,11 +237,6 @@ class Controls extends FlxActionSet inline function get_DEBUG_STAGE() return _debug_stage.check(); - public var SCREENSHOT(get, never):Bool; - - inline function get_SCREENSHOT() - return _screenshot.check(); - public var VOLUME_UP(get, never):Bool; inline function get_VOLUME_UP() @@ -253,11 +252,6 @@ class Controls extends FlxActionSet inline function get_VOLUME_MUTE() return _volume_mute.check(); - public var RESET(get, never):Bool; - - inline function get_RESET() - return _reset.check(); - public function new(name, scheme:KeyboardScheme = null) { super(name); @@ -289,16 +283,15 @@ class Controls extends FlxActionSet add(_accept); add(_back); add(_pause); + add(_reset); + add(_screenshot); add(_cutscene_advance); - add(_cutscene_skip); add(_debug_menu); add(_debug_chart); add(_debug_stage); - add(_screenshot); add(_volume_up); add(_volume_down); add(_volume_mute); - add(_reset); for (action in digitalActions) byName[action.name] = action; @@ -383,12 +376,11 @@ class Controls extends FlxActionSet case BACK: _back; case PAUSE: _pause; case RESET: _reset; + case SCREENSHOT: _screenshot; case CUTSCENE_ADVANCE: _cutscene_advance; - case CUTSCENE_SKIP: _cutscene_skip; case DEBUG_MENU: _debug_menu; case DEBUG_CHART: _debug_chart; case DEBUG_STAGE: _debug_stage; - case SCREENSHOT: _screenshot; case VOLUME_UP: _volume_up; case VOLUME_DOWN: _volume_down; case VOLUME_MUTE: _volume_mute; @@ -449,26 +441,24 @@ class Controls extends FlxActionSet func(_back, JUST_PRESSED); case PAUSE: func(_pause, JUST_PRESSED); + case RESET: + func(_reset, JUST_PRESSED); + case SCREENSHOT: + func(_screenshot, JUST_PRESSED); case CUTSCENE_ADVANCE: func(_cutscene_advance, JUST_PRESSED); - case CUTSCENE_SKIP: - func(_cutscene_skip, PRESSED); case DEBUG_MENU: func(_debug_menu, JUST_PRESSED); case DEBUG_CHART: func(_debug_chart, JUST_PRESSED); case DEBUG_STAGE: func(_debug_stage, JUST_PRESSED); - case SCREENSHOT: - func(_screenshot, JUST_PRESSED); case VOLUME_UP: func(_volume_up, JUST_PRESSED); case VOLUME_DOWN: func(_volume_down, JUST_PRESSED); case VOLUME_MUTE: func(_volume_mute, JUST_PRESSED); - case RESET: - func(_reset, JUST_PRESSED); } } @@ -654,13 +644,12 @@ class Controls extends FlxActionSet bindKeys(Control.ACCEPT, getDefaultKeybinds(scheme, Control.ACCEPT)); bindKeys(Control.BACK, getDefaultKeybinds(scheme, Control.BACK)); bindKeys(Control.PAUSE, getDefaultKeybinds(scheme, Control.PAUSE)); + bindKeys(Control.RESET, getDefaultKeybinds(scheme, Control.RESET)); + bindKeys(Control.SCREENSHOT, getDefaultKeybinds(scheme, Control.SCREENSHOT)); bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE)); - bindKeys(Control.CUTSCENE_SKIP, getDefaultKeybinds(scheme, Control.CUTSCENE_SKIP)); bindKeys(Control.DEBUG_MENU, getDefaultKeybinds(scheme, Control.DEBUG_MENU)); bindKeys(Control.DEBUG_CHART, getDefaultKeybinds(scheme, Control.DEBUG_CHART)); bindKeys(Control.DEBUG_STAGE, getDefaultKeybinds(scheme, Control.DEBUG_STAGE)); - bindKeys(Control.RESET, getDefaultKeybinds(scheme, Control.RESET)); - bindKeys(Control.SCREENSHOT, getDefaultKeybinds(scheme, Control.SCREENSHOT)); bindKeys(Control.VOLUME_UP, getDefaultKeybinds(scheme, Control.VOLUME_UP)); bindKeys(Control.VOLUME_DOWN, getDefaultKeybinds(scheme, Control.VOLUME_DOWN)); bindKeys(Control.VOLUME_MUTE, getDefaultKeybinds(scheme, Control.VOLUME_MUTE)); @@ -683,16 +672,15 @@ class Controls extends FlxActionSet case Control.ACCEPT: return [Z, SPACE, ENTER]; case Control.BACK: return [X, BACKSPACE, ESCAPE]; case Control.PAUSE: return [P, ENTER, ESCAPE]; + case Control.RESET: return [R]; + case Control.SCREENSHOT: return [F3]; // TODO: Change this back to PrintScreen case Control.CUTSCENE_ADVANCE: return [Z, ENTER]; - case Control.CUTSCENE_SKIP: return [P, ESCAPE]; case Control.DEBUG_MENU: return [GRAVEACCENT]; case Control.DEBUG_CHART: return []; case Control.DEBUG_STAGE: return []; - case Control.SCREENSHOT: return [F3]; // TODO: Change this back to PrintScreen case Control.VOLUME_UP: return [PLUS, NUMPADPLUS]; case Control.VOLUME_DOWN: return [MINUS, NUMPADMINUS]; case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO]; - case Control.RESET: return [R]; } case Duo(true): switch (control) { @@ -707,16 +695,15 @@ class Controls extends FlxActionSet case Control.ACCEPT: return [G, Z]; case Control.BACK: return [H, X]; case Control.PAUSE: return [ONE]; + case Control.RESET: return [R]; + case Control.SCREENSHOT: return [PRINTSCREEN]; case Control.CUTSCENE_ADVANCE: return [G, Z]; - case Control.CUTSCENE_SKIP: return [ONE]; case Control.DEBUG_MENU: return [GRAVEACCENT]; case Control.DEBUG_CHART: return []; case Control.DEBUG_STAGE: return []; - case Control.SCREENSHOT: return [PRINTSCREEN]; case Control.VOLUME_UP: return [PLUS]; case Control.VOLUME_DOWN: return [MINUS]; case Control.VOLUME_MUTE: return [ZERO]; - case Control.RESET: return [R]; } case Duo(false): switch (control) { @@ -731,16 +718,15 @@ class Controls extends FlxActionSet case Control.ACCEPT: return [ENTER]; case Control.BACK: return [ESCAPE]; case Control.PAUSE: return [ONE]; + case Control.RESET: return [R]; + case Control.SCREENSHOT: return [PRINTSCREEN]; case Control.CUTSCENE_ADVANCE: return [ENTER]; - case Control.CUTSCENE_SKIP: return [ONE]; case Control.DEBUG_MENU: return [GRAVEACCENT]; case Control.DEBUG_CHART: return []; case Control.DEBUG_STAGE: return []; - case Control.SCREENSHOT: return [PRINTSCREEN]; case Control.VOLUME_UP: return [NUMPADPLUS]; case Control.VOLUME_DOWN: return [NUMPADMINUS]; case Control.VOLUME_MUTE: return [NUMPADZERO]; - case Control.RESET: return [R]; } default: // Fallthrough. @@ -843,15 +829,14 @@ class Controls extends FlxActionSet Control.NOTE_LEFT => getDefaultGamepadBinds(Control.NOTE_LEFT), Control.NOTE_RIGHT => getDefaultGamepadBinds(Control.NOTE_RIGHT), Control.PAUSE => getDefaultGamepadBinds(Control.PAUSE), + Control.RESET => getDefaultGamepadBinds(Control.RESET), // Control.SCREENSHOT => [], // Control.VOLUME_UP => [RIGHT_SHOULDER], // Control.VOLUME_DOWN => [LEFT_SHOULDER], // Control.VOLUME_MUTE => [RIGHT_TRIGGER], Control.CUTSCENE_ADVANCE => getDefaultGamepadBinds(Control.CUTSCENE_ADVANCE), - Control.CUTSCENE_SKIP => getDefaultGamepadBinds(Control.CUTSCENE_SKIP), // Control.DEBUG_MENU // Control.DEBUG_CHART - Control.RESET => getDefaultGamepadBinds(Control.RESET) ]); } @@ -868,15 +853,14 @@ class Controls extends FlxActionSet case Control.NOTE_LEFT: return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT]; case Control.NOTE_RIGHT: return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT]; case Control.PAUSE: return [START]; + case Control.RESET: return [RIGHT_SHOULDER]; case Control.SCREENSHOT: return []; case Control.VOLUME_UP: return []; case Control.VOLUME_DOWN: return []; case Control.VOLUME_MUTE: return []; case Control.CUTSCENE_ADVANCE: return [A]; - case Control.CUTSCENE_SKIP: return [START]; case Control.DEBUG_MENU: return []; case Control.DEBUG_CHART: return []; - case Control.RESET: return [RIGHT_SHOULDER]; default: // Fallthrough. } @@ -1228,14 +1212,13 @@ enum Control UI_RIGHT; UI_DOWN; RESET; + SCREENSHOT; ACCEPT; BACK; PAUSE; // CUTSCENE CUTSCENE_ADVANCE; - CUTSCENE_SKIP; // SCREENSHOT - SCREENSHOT; // VOLUME VOLUME_UP; VOLUME_DOWN; @@ -1279,15 +1262,14 @@ abstract Action(String) to String from String var BACK = "back"; var PAUSE = "pause"; var RESET = "reset"; + // SCREENSHOT + var SCREENSHOT = "screenshot"; // CUTSCENE var CUTSCENE_ADVANCE = "cutscene_advance"; - var CUTSCENE_SKIP = "cutscene_skip"; // VOLUME var VOLUME_UP = "volume_up"; var VOLUME_DOWN = "volume_down"; var VOLUME_MUTE = "volume_mute"; - // SCREENSHOT - var SCREENSHOT = "screenshot"; // DEBUG var DEBUG_MENU = "debug_menu"; var DEBUG_CHART = "debug_chart"; diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index 8300ac936..4f2a76e19 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -1,5 +1,24 @@ package funkin.play; +import flixel.addons.transition.FlxTransitionableState; +import flixel.FlxG; +import flixel.util.FlxTimer; +import flixel.FlxSprite; +import flixel.group.FlxSpriteGroup; +import flixel.math.FlxMath; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import funkin.audio.FunkinSound; +import funkin.data.song.SongRegistry; +import funkin.graphics.FunkinSprite; +import funkin.play.cutscene.VideoCutscene; +import funkin.play.PlayState; +import funkin.ui.AtlasText; +import funkin.ui.MusicBeatSubState; +import funkin.ui.transition.StickerSubState; + typedef PauseSubStateParams = { ?mode:PauseMode, @@ -10,29 +29,36 @@ typedef PauseSubStateParams = */ class PauseSubState extends MusicBeatSubState { - static final PAUSE_MENU_ENTRIES_STANDARD = [ + static final PAUSE_MENU_ENTRIES_STANDARD:Array<PauseMenuEntry> = [ {text: 'Resume', callback: resume}, {text: 'Restart Song', callback: restartPlayState}, {text: 'Change Difficulty', callback: switchMode.bind(_, Difficulty)}, - {text: 'Enable Practice Mode', callback: enablePracticeMode, filter: () -> (PlayState.instance?.isPracticeMode ?? true)}, + {text: 'Enable Practice Mode', callback: enablePracticeMode, filter: () -> !(PlayState.instance?.isPracticeMode ?? false)}, {text: 'Exit to Menu', callback: quitToMenu}, ]; - static final PAUSE_MENU_ENTRIES_CHARTING = [ + static final PAUSE_MENU_ENTRIES_CHARTING:Array<PauseMenuEntry> = [ {text: 'Resume', callback: resume}, {text: 'Restart Song', callback: restartPlayState}, {text: 'Return to Chart Editor', callback: quitToChartEditor}, ]; - static final PAUSE_MENU_ENTRIES_DIFFICULTY = [ + static final PAUSE_MENU_ENTRIES_DIFFICULTY:Array<PauseMenuEntry> = [ {text: 'Back', callback: switchMode.bind(_, Standard)} // Other entries are added dynamically. ]; - static final PAUSE_MENU_ENTRIES_CUTSCENE = [ + static final PAUSE_MENU_ENTRIES_VIDEO_CUTSCENE:Array<PauseMenuEntry> = [ {text: 'Resume', callback: resume}, - {text: 'Restart Cutscene', callback: restartCutscene}, - {text: 'Skip Cutscene', callback: skipCutscene}, + {text: 'Restart Cutscene', callback: restartVideoCutscene}, + {text: 'Skip Cutscene', callback: skipVideoCutscene}, + {text: 'Exit to Menu', callback: quitToMenu}, + ]; + + static final PAUSE_MENU_ENTRIES_CONVERSATION:Array<PauseMenuEntry> = [ + {text: 'Resume', callback: resume}, + {text: 'Restart Dialogue', callback: restartConversation}, + {text: 'Skip Dialogue', callback: skipConversation}, {text: 'Exit to Menu', callback: quitToMenu}, ]; @@ -42,15 +68,21 @@ class PauseSubState extends MusicBeatSubState public static var musicSuffix:String = ''; // Status - var menuEntries:Array<PauseMenuEntry>; + var currentMenuEntries:Array<PauseMenuEntry>; var currentEntry:Int = 0; var currentMode:PauseMode; - var allowInput:Bool = true; + + /** + * Disallow input until the transition in is complete! + * This prevents the pause menu from immediately closing. + */ + public var allowInput:Bool = false; // Graphics - var metadata:FlxTypedGroup<FlxText>; + var background:FunkinSprite; + var metadata:FlxTypedSpriteGroup<FlxText>; var metadataPractice:FlxText; - var menuEntryText:FlxTypedGroup<AtlasText>; + var menuEntryText:FlxTypedSpriteGroup<AtlasText>; // Audio var pauseMusic:FunkinSound; @@ -58,9 +90,7 @@ class PauseSubState extends MusicBeatSubState public function new(?params:PauseSubStateParams) { super(); - this.currentMode = params?.mode ?? PauseMode.Standard; - - this.bgColor = FlxColor.TRANSPARENT; // Transparent, fades into black later. + this.currentMode = params?.mode ?? Standard; } public override function create():Void @@ -69,8 +99,16 @@ class PauseSubState extends MusicBeatSubState startPauseMusic(); + buildBackground(); + buildMetadata(); + menuEntryText = new FlxTypedSpriteGroup<AtlasText>(); + menuEntryText.scrollFactor.set(0, 0); + add(menuEntryText); + + regenerateMenu(); + transitionIn(); } @@ -81,47 +119,69 @@ class PauseSubState extends MusicBeatSubState handleInputs(); } + public override function destroy():Void + { + super.destroy(); + pauseMusic.stop(); + } + function startPauseMusic():Void { - pauseMusic = FunkinSound.load(Paths.music('breakfast-pixel'), true, true); + pauseMusic = FunkinSound.load(Paths.music('breakfast$musicSuffix'), true, true); // Start playing at a random point in the song. pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2))); pauseMusic.fadeIn(MUSIC_FADE_IN_TIME, 0, MUSIC_FINAL_VOLUME); } + function buildBackground():Void + { + // Using state.bgColor causes bugs! + background = new FunkinSprite(0, 0); + background.makeSolidColor(FlxG.width, FlxG.height, FlxColor.BLACK); + background.alpha = 0.0; + background.scrollFactor.set(0, 0); + background.updateHitbox(); + add(background); + } + /** * Render the metadata in the top right. */ function buildMetadata():Void { - metadata = new FlxTypedGroup<FlxSprite>(); + metadata = new FlxTypedSpriteGroup<FlxText>(); + metadata.scrollFactor.set(0, 0); add(metadata); - var metadataSong:FlxText = new FlxText(20, 15, 0, 'Song Name - Artist'); + var metadataSong:FlxText = new FlxText(20, 15, FlxG.width - 40, 'Song Name - Artist'); 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} - ${PlayState.instance.currentChart.songArtist}'; } + metadataSong.scrollFactor.set(0, 0); metadata.add(metadataSong); - var metadataDifficulty:FlxText = new FlxText(20, 15 + 32, 0, 'Difficulty'); + var metadataDifficulty:FlxText = new FlxText(20, 15 + 32, FlxG.width - 40, 'Difficulty: '); metadataDifficulty.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); if (PlayState.instance?.currentDifficulty != null) { metadataDifficulty.text += PlayState.instance.currentDifficulty.toTitleCase(); } + metadataDifficulty.scrollFactor.set(0, 0); metadata.add(metadataDifficulty); - var metadataDeaths:FlxText = new FlxText(20, 15 + 64, 0, '0 Blue Balls'); + var metadataDeaths:FlxText = new FlxText(20, 15 + 64, FlxG.width - 40, '0 Blue Balls'); metadataDeaths.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); metadataDeaths.text = '${PlayState.instance?.deathCounter} Blue Balls'; + metadataDeaths.scrollFactor.set(0, 0); metadata.add(metadataDeaths); - metadataPractice = new FlxText(20, 15 + 96, 0, 'PRACTICE MODE'); + metadataPractice = new FlxText(20, 15 + 96, 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); metadata.add(metadataPractice); } @@ -149,30 +209,45 @@ class PauseSubState extends MusicBeatSubState trace('DIFFICULTIES: ${difficultiesInVariation}'); for (difficulty in difficultiesInVariation) { - difficulties.push({text: difficulty.toTitleCase(), callback: () -> changeDifficulty(this, difficulty)}); + entries.push({text: difficulty.toTitleCase(), callback: (state) -> changeDifficulty(state, difficulty)}); } } // Add the back button. currentMenuEntries = entries.concat(PAUSE_MENU_ENTRIES_DIFFICULTY.clone()); + case PauseMode.Conversation: + currentMenuEntries = PAUSE_MENU_ENTRIES_CONVERSATION.clone(); case PauseMode.Cutscene: - currentMenuEntries = PAUSE_MENU_ENTRIES_CUTSCENE.clone(); + currentMenuEntries = PAUSE_MENU_ENTRIES_VIDEO_CUTSCENE.clone(); } // Render out the entries depending on the mode. - for (entryIndex in 0...entries) + var entryIndex:Int = 0; + var toRemove = []; + for (entry in currentMenuEntries) { - var entry:PauseMenuEntry = entries[entryIndex]; + if (entry == null || (entry.filter != null && !entry.filter())) + { + // Remove entries that should be hidden. + toRemove.push(entry); + } + else + { + // Handle visible entries. + var yPos:Float = 70 * entryIndex + 30; + var text:AtlasText = new AtlasText(0, yPos, entry.text, AtlasFont.BOLD); + text.scrollFactor.set(0, 0); + text.alpha = 0; + menuEntryText.add(text); - // Remove entries that should be hidden. - if (entry.filter != null && !entry.filter()) currentMenuEntries.remove(entry); + entry.sprite = text; - var yPos:Float = 70 * entryIndex + 30; - var text:AtlasText = new AtlasText(0, yPos, entry.text, AtlasFont.BOLD); - text.alpha = 0; - menuEntryText.add(text); - - entry.sprite = text; + entryIndex++; + } + } + for (entry in toRemove) + { + currentMenuEntries.remove(entry); } metadataPractice.visible = PlayState.instance?.isPracticeMode ?? false; @@ -182,15 +257,19 @@ class PauseSubState extends MusicBeatSubState function transitionIn():Void { - FlxTween.globalManager.bgColor(this, 0.4, FlxColor.fromRGB(0, 0, 0, 0.0), FlxColor.fromRGB(0, 0, 0, 0.6), {ease: FlxEase.quartInOut}); + FlxTween.tween(background, {alpha: 0.6}, 0.4, {ease: FlxEase.quartInOut}); // Animate each element a little bit downwards. - var delay:Float = 0.3; + var delay:Float = 0.1; for (child in metadata.members) { FlxTween.tween(child, {alpha: 1, y: child.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: delay}); - delay += 0.2; + delay += 0.05; } + + new FlxTimer().start(0.2, (_) -> { + allowInput = true; + }); } function handleInputs():Void @@ -205,22 +284,24 @@ class PauseSubState extends MusicBeatSubState { changeSelection(1); } - if (controls.PAUSE) - { - resume(this); - } + if (controls.ACCEPT) { - menuEntries[currentEntry].callback(this); + currentMenuEntries[currentEntry].callback(this); + } + else if (controls.PAUSE) + { + resume(this); } #if (debug || FORCE_DEBUG_VERSION) // to pause the game and get screenshots easy, press H on pause menu! if (FlxG.keys.justPressed.H) { - var visible = !metaDataGrp.visible; - metadata = visible; - menuEntryText = visible; + var visible = !metadata.visible; + + metadata.visible = visible; + menuEntryText.visible = visible; this.bgColor = visible ? 0x99000000 : 0x00000000; // 60% or fully transparent black } #end @@ -232,14 +313,14 @@ class PauseSubState extends MusicBeatSubState currentEntry += change; - if (currentEntry < 0) currentEntry = menuEntries.length - 1; - if (currentEntry >= menuEntries.length) currentEntry = 0; + if (currentEntry < 0) currentEntry = currentMenuEntries.length - 1; + if (currentEntry >= currentMenuEntries.length) currentEntry = 0; - for (entryIndex in 0...menuEntries.length) + for (entryIndex in 0...currentMenuEntries.length) { var isCurrent:Bool = entryIndex == currentEntry; - var entry:PauseMenuEntry = menuEntries[entryIndex]; + var entry:PauseMenuEntry = currentMenuEntries[entryIndex]; var text:AtlasText = entry.sprite; // Set the transparency. @@ -248,6 +329,7 @@ class PauseSubState extends MusicBeatSubState // Set the position. var targetX = FlxMath.remapToRange((entryIndex - currentEntry), 0, 1, 0, 1.3) * 20 + 90; var targetY = FlxMath.remapToRange((entryIndex - currentEntry), 0, 1, 0, 1.3) * 120 + (FlxG.height * 0.48); + trace(targetY); FlxTween.tween(text, {x: targetX, y: targetY}, 0.16, {ease: FlxEase.linear}); } } @@ -291,7 +373,35 @@ class PauseSubState extends MusicBeatSubState if (PlayState.instance == null) return; PlayState.instance.isPracticeMode = true; - regenerateMenu(); + state.regenerateMenu(); + } + + static function restartVideoCutscene(state:PauseSubState):Void + { + VideoCutscene.restartVideo(); + state.close(); + } + + static function skipVideoCutscene(state:PauseSubState):Void + { + VideoCutscene.finishVideo(); + state.close(); + } + + static function restartConversation(state:PauseSubState):Void + { + if (PlayState.instance?.currentConversation == null) return; + + PlayState.instance.currentConversation.resetConversation(); + state.close(); + } + + static function skipConversation(state:PauseSubState):Void + { + if (PlayState.instance?.currentConversation == null) return; + + PlayState.instance.currentConversation.skipConversation(); + state.close(); } static function quitToMenu(state:PauseSubState):Void @@ -306,11 +416,11 @@ class PauseSubState extends MusicBeatSubState if (PlayStatePlaylist.isStoryMode) { PlayStatePlaylist.reset(); - openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.story.StoryMenuState(sticker))); + state.openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.story.StoryMenuState(sticker))); } else { - openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.freeplay.FreeplayState(null, sticker))); + state.openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new funkin.ui.freeplay.FreeplayState(null, sticker))); } } @@ -351,7 +461,12 @@ enum PauseMode Difficulty; /** - * The menu displayed when the player pauses the game during a cutscene. + * The menu displayed when the player pauses the game during a conversation. + */ + Conversation; + + /** + * The menu displayed when the player pauses the game during a video cutscene. */ Cutscene; } diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 1dbba5b54..ca2344b0a 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -314,6 +314,11 @@ class PlayState extends MusicBeatSubState **/ var inputReleaseQueue:Array<PreciseInputEvent> = []; + /** + * If we just unpaused the game, we shouldn't be able to pause again for one frame. + */ + var justUnpaused:Bool = false; + /** * PRIVATE INSTANCE VARIABLES * Private instance variables should be used for information that must be reset or dereferenced @@ -442,11 +447,6 @@ class PlayState extends MusicBeatSubState */ var comboPopUps:PopUpStuff; - /** - * The circular sprite that appears while the user is holding down the Skip Cutscene button. - */ - var skipTimer:FlxPieDial; - /** * PROPERTIES */ @@ -474,7 +474,7 @@ class PlayState extends MusicBeatSubState if (!Std.isOfType(this.subState, PauseSubState)) return false; var pauseSubState:PauseSubState = cast this.subState; - return pauseSubState.exitingToMenu; + return !pauseSubState.allowInput; } /** @@ -629,14 +629,6 @@ class PlayState extends MusicBeatSubState comboPopUps.cameras = [camHUD]; add(comboPopUps); - // The little dial that shows up when you hold the Skip Cutscene key. - skipTimer = new FlxPieDial(16, 16, 32, FlxColor.WHITE, 36, CIRCLE, true, 24); - skipTimer.amount = 0; - skipTimer.zIndex = 1000; - add(skipTimer); - // Renders only in video cutscene mode. - skipTimer.cameras = [camCutscene]; - #if discord_rpc // Initialize Discord Rich Presence. initDiscord(); @@ -752,6 +744,8 @@ class PlayState extends MusicBeatSubState public override function update(elapsed:Float):Void { + // TOTAL: 9.42% CPU Time when profiled in VS 2019. + if (criticalFailure) return; super.update(elapsed); @@ -853,7 +847,7 @@ class PlayState extends MusicBeatSubState #end // Attempt to pause the game. - if ((controls.PAUSE || androidPause) && isInCountdown && mayPauseGame) + if ((controls.PAUSE || androidPause) && isInCountdown && mayPauseGame && !justUnpaused) { var event = new PauseScriptEvent(FlxG.random.bool(1 / 1000)); @@ -888,12 +882,12 @@ class PlayState extends MusicBeatSubState boyfriendPos = currentStage.getBoyfriend().getScreenPosition(); } - var pauseSubState:FlxSubState = new PauseSubState(isChartingMode); + var pauseSubState:FlxSubState = new PauseSubState({mode: isChartingMode ? Charting : Standard}); FlxTransitionableSubState.skipNextTransIn = true; FlxTransitionableSubState.skipNextTransOut = true; - openSubState(pauseSubState); pauseSubState.camera = camHUD; + openSubState(pauseSubState); // boyfriendPos.put(); // TODO: Why is this here? } @@ -1017,6 +1011,8 @@ class PlayState extends MusicBeatSubState // Moving notes into position is now done by Strumline.update(). processNotes(elapsed); + + justUnpaused = false; } public override function dispatchEvent(event:ScriptEvent):Void @@ -1105,6 +1101,8 @@ class PlayState extends MusicBeatSubState DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC); } #end + + justUnpaused = true; } else if (Std.isOfType(subState, Transition)) { @@ -2444,58 +2442,39 @@ class PlayState extends MusicBeatSubState */ function handleCutsceneKeys(elapsed:Float):Void { + if (isGamePaused) return; + if (currentConversation != null) { - if (controls.CUTSCENE_ADVANCE) currentConversation?.advanceConversation(); - - if (controls.CUTSCENE_SKIP) + // Pause/unpause may conflict with advancing the conversation! + if (controls.CUTSCENE_ADVANCE && !justUnpaused) { - currentConversation?.trySkipConversation(elapsed); + currentConversation?.advanceConversation(); } - else + else if (controls.PAUSE && !justUnpaused) { - currentConversation?.trySkipConversation(-1); + var pauseSubState:FlxSubState = new PauseSubState({mode: Conversation}); + + persistentUpdate = false; + FlxTransitionableSubState.skipNextTransIn = true; + FlxTransitionableSubState.skipNextTransOut = true; + pauseSubState.camera = camCutscene; + openSubState(pauseSubState); } } else if (VideoCutscene.isPlaying()) { // This is a video cutscene. - - if (controls.CUTSCENE_SKIP) + if (controls.PAUSE && !justUnpaused) { - trySkipVideoCutscene(elapsed); + var pauseSubState:FlxSubState = new PauseSubState({mode: Cutscene}); + + persistentUpdate = false; + FlxTransitionableSubState.skipNextTransIn = true; + FlxTransitionableSubState.skipNextTransOut = true; + pauseSubState.camera = camCutscene; + openSubState(pauseSubState); } - else - { - trySkipVideoCutscene(-1); - } - } - } - - /** - * Handle logic for the skip timer. - * If the skip button is being held, pass the amount of time elapsed since last game update. - * If the skip button has been released, pass a negative number. - */ - function trySkipVideoCutscene(elapsed:Float):Void - { - if (skipTimer == null || skipTimer.animation == null) return; - - if (elapsed < 0) - { - skipHeldTimer = 0.0; - } - else - { - skipHeldTimer += elapsed; - } - - skipTimer.visible = skipHeldTimer >= 0.05; - skipTimer.amount = Math.min(skipHeldTimer / 1.5, 1.0); - - if (skipHeldTimer >= 1.5) - { - VideoCutscene.finishVideo(); } } @@ -2694,7 +2673,7 @@ class PlayState extends MusicBeatSubState FlxG.sound.music.pause(); if (vocals != null) { - vocals.pause(); + vocals.destroy(); remove(vocals); } } diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 934919b65..a883a528a 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -118,6 +118,24 @@ class VideoCutscene } #end + public static function restartVideo():Void + { + #if html5 + if (vid != null) + { + vid.restartVideo(); + } + #end + + #if hxCodec + if (vid != null) + { + // Seek to the start of the video. + vid.bitmap.time = 0; + } + #end + } + public static function finishVideo(?transitionTime:Float = 0.5):Void { trace('ALERT: Finish video cutscene called!'); diff --git a/source/funkin/play/cutscene/dialogue/Conversation.hx b/source/funkin/play/cutscene/dialogue/Conversation.hx index dc3fd8c8a..150f6bf6f 100644 --- a/source/funkin/play/cutscene/dialogue/Conversation.hx +++ b/source/funkin/play/cutscene/dialogue/Conversation.hx @@ -31,10 +31,6 @@ import funkin.data.dialogue.DialogueBoxRegistry; */ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass implements IRegistryEntry<ConversationData> { - static final CONVERSATION_SKIP_TIMER:Float = 1.5; - - var skipHeldTimer:Float = 0.0; - /** * The ID of the conversation. */ @@ -105,8 +101,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl var currentDialogueBox:DialogueBox; - var skipTimer:FlxPieDial; - public function new(id:String) { super(); @@ -124,8 +118,8 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl { // Reset the progress in the dialogue. currentDialogueEntry = 0; + currentDialogueLine = 0; this.state = ConversationState.Start; - this.alpha = 1.0; // Start the dialogue. dispatchEvent(new DialogueScriptEvent(DIALOGUE_START, this, false)); @@ -153,6 +147,12 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl function setupBackdrop():Void { + if (backdrop != null) + { + backdrop.destroy(); + backdrop = null; + } + backdrop = new FunkinSprite(0, 0); if (_data.backdrop == null) return; @@ -181,12 +181,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl refresh(); } - function setupSkipTimer():Void - { - add(skipTimer = new FlxPieDial(16, 16, 32, FlxColor.WHITE, 36, CIRCLE, true, 24)); - skipTimer.amount = 0; - } - public override function update(elapsed:Float):Void { super.update(elapsed); @@ -201,8 +195,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl // Skip the next steps if the current speaker is already displayed. if (currentSpeaker != null && nextSpeakerId == currentSpeaker.id) return; - var nextSpeaker:Speaker = SpeakerRegistry.instance.fetchEntry(nextSpeakerId); - if (currentSpeaker != null) { remove(currentSpeaker); @@ -210,6 +202,8 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl currentSpeaker = null; } + var nextSpeaker:Speaker = SpeakerRegistry.instance.fetchEntry(nextSpeakerId); + if (nextSpeaker == null) { if (nextSpeakerId == null) @@ -222,6 +216,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl } return; } + if (!nextSpeaker.alive) nextSpeaker.revive(); ScriptEventDispatcher.callEvent(nextSpeaker, new ScriptEvent(CREATE, true)); @@ -266,6 +261,7 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl trace('Dialogue box could not be retrieved.'); return; } + if (!nextDialogueBox.alive) nextDialogueBox.revive(); ScriptEventDispatcher.callEvent(nextDialogueBox, new ScriptEvent(CREATE, true)); @@ -347,29 +343,21 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl currentDialogueEntry = 0; this.state = ConversationState.Start; - advanceConversation(); - } + if (outroTween != null) outroTween.cancel(); // Canc + outroTween = null; - public function trySkipConversation(elapsed:Float):Void - { - if (skipTimer == null || skipTimer.animation == null) return; + this.alpha = 0.0; + if (this.music != null) this.music.stop(); + this.music = null; - if (elapsed < 0) - { - skipHeldTimer = 0.0; - } - else - { - skipHeldTimer += elapsed; - } + if (currentSpeaker != null) currentSpeaker.kill(); + currentSpeaker = null; + if (currentDialogueBox != null) currentDialogueBox.kill(); + currentDialogueBox = null; + if (backdrop != null) backdrop.kill(); + backdrop = null; - skipTimer.visible = skipHeldTimer >= 0.05; - skipTimer.amount = Math.min(skipHeldTimer / CONVERSATION_SKIP_TIMER, 1.0); - - if (skipHeldTimer >= CONVERSATION_SKIP_TIMER) - { - skipConversation(); - } + startConversation(); } /** @@ -425,7 +413,6 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl // Fade in the music and backdrop. setupMusic(); setupBackdrop(); - setupSkipTimer(); // Advance the conversation. state = ConversationState.Opening; @@ -554,12 +541,16 @@ class Conversation extends FlxSpriteGroup implements IDialogueScriptedClass impl if (this.music != null) this.music.stop(); this.music = null; - this.skipTimer = null; if (currentSpeaker != null) currentSpeaker.kill(); + remove(currentSpeaker); currentSpeaker = null; + if (currentDialogueBox != null) currentDialogueBox.kill(); + remove(currentDialogueBox); currentDialogueBox = null; + if (backdrop != null) backdrop.kill(); + remove(backdrop); backdrop = null; this.clear(); diff --git a/source/funkin/play/cutscene/dialogue/DialogueBox.hx b/source/funkin/play/cutscene/dialogue/DialogueBox.hx index 6f8a0086a..eb603a352 100644 --- a/source/funkin/play/cutscene/dialogue/DialogueBox.hx +++ b/source/funkin/play/cutscene/dialogue/DialogueBox.hx @@ -8,6 +8,7 @@ import flixel.text.FlxText; import flixel.addons.text.FlxTypeText; import funkin.util.assets.FlxAnimationUtil; import funkin.modding.events.ScriptEvent; +import funkin.audio.FunkinSound; import funkin.modding.IScriptedClass.IDialogueScriptedClass; import flixel.util.FlxColor; import funkin.data.dialogue.DialogueBoxData; @@ -111,9 +112,6 @@ class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass imple this.y = 0; this.alpha = 1; - this.boxSprite = new FlxSprite(0, 0); - add(this.boxSprite); - loadSpritesheet(); loadAnimations(); @@ -122,6 +120,15 @@ class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass imple function loadSpritesheet():Void { + if (this.boxSprite != null) + { + remove(this.boxSprite); + this.boxSprite = null; + } + + this.boxSprite = new FlxSprite(0, 0); + add(this.boxSprite); + trace('[DIALOGUE BOX] Loading spritesheet ${_data.assetPath} for ${id}'); var tex:FlxFramesCollection = Paths.getSparrowAtlas(_data.assetPath); @@ -190,6 +197,31 @@ class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass imple this.boxSprite.updateHitbox(); } + /** + * Calls `kill()` on the group's members and then on the group itself. + * You can revive this group later via `revive()` after this. + */ + public override function kill():Void + { + super.kill(); + if (this.boxSprite != null) + { + this.boxSprite.kill(); + this.boxSprite = null; + } + if (this.textDisplay != null) + { + this.textDisplay.kill(); + this.textDisplay = null; + } + this.clear(); + } + + public override function revive():Void + { + super.revive(); + } + function loadAnimations():Void { trace('[DIALOGUE BOX] Loading ${_data.animations.length} animations for ${id}'); @@ -246,7 +278,8 @@ class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass imple textDisplay.setFormat(_data.text.fontFamily, _data.text.size, FlxColor.fromString(_data.text.color), LEFT, SHADOW, FlxColor.fromString(_data.text.shadowColor ?? '#00000000'), false); textDisplay.borderSize = _data.text.shadowWidth ?? 2; - textDisplay.sounds = [FlxG.sound.load(Paths.sound('pixelText'), 0.6)]; + // TODO: Add an option to configure this. + textDisplay.sounds = [FunkinSound.load(Paths.sound('pixelText'), 0.6)]; textDisplay.completeCallback = onTypingComplete; diff --git a/source/funkin/play/cutscene/dialogue/Speaker.hx b/source/funkin/play/cutscene/dialogue/Speaker.hx index d5bffd7b0..0d59854a7 100644 --- a/source/funkin/play/cutscene/dialogue/Speaker.hx +++ b/source/funkin/play/cutscene/dialogue/Speaker.hx @@ -106,6 +106,23 @@ class Speaker extends FlxSprite implements IDialogueScriptedClass implements IRe loadAnimations(); } + /** + * Calls `kill()` on the group's members and then on the group itself. + * You can revive this group later via `revive()` after this. + */ + public override function kill():Void + { + super.kill(); + } + + public override function revive():Void + { + super.revive(); + + loadSpritesheet(); + loadAnimations(); + } + function loadSpritesheet():Void { trace('[SPEAKER] Loading spritesheet ${_data.assetPath} for ${id}'); diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 970aebc57..105e6db43 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -614,9 +614,9 @@ class SongDifficulty } // Add player vocals. - if (voiceList[0] != null) result.addPlayerVoice(FunkinSound.load(Assets.getSound(voiceList[0]))); + if (voiceList[0] != null) result.addPlayerVoice(FunkinSound.load(voiceList[0])); // Add opponent vocals. - if (voiceList[1] != null) result.addOpponentVoice(FunkinSound.load(Assets.getSound(voiceList[1]))); + if (voiceList[1] != null) result.addOpponentVoice(FunkinSound.load(voiceList[1])); // Add additional vocals. if (voiceList.length > 2) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index ff5e5bfb8..6246dcb58 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -893,12 +893,6 @@ typedef SaveControlsData = */ var ?CUTSCENE_ADVANCE:Array<Int>; - /** - * Keybind for skipping a cutscene. - * @default `Escape` - */ - var ?CUTSCENE_SKIP:Array<Int>; - /** * Keybind for increasing volume. * @default `Plus` diff --git a/source/funkin/save/migrator/RawSaveData_v1_0_0.hx b/source/funkin/save/migrator/RawSaveData_v1_0_0.hx index b71102cce..a516f944a 100644 --- a/source/funkin/save/migrator/RawSaveData_v1_0_0.hx +++ b/source/funkin/save/migrator/RawSaveData_v1_0_0.hx @@ -35,7 +35,6 @@ typedef SaveControlsData_v1_0_0 = var ?ACCEPT:Array<Int>; var ?BACK:Array<Int>; var ?CUTSCENE_ADVANCE:Array<Int>; - var ?CUTSCENE_SKIP:Array<Int>; var ?NOTE_DOWN:Array<Int>; var ?NOTE_LEFT:Array<Int>; var ?NOTE_RIGHT:Array<Int>; diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx index 92bee4ceb..f995660f7 100644 --- a/source/funkin/save/migrator/SaveDataMigrator.hx +++ b/source/funkin/save/migrator/SaveDataMigrator.hx @@ -272,7 +272,6 @@ class SaveDataMigrator ACCEPT: controlsData?.keys?.ACCEPT ?? null, BACK: controlsData?.keys?.BACK ?? null, CUTSCENE_ADVANCE: controlsData?.keys?.CUTSCENE_ADVANCE ?? null, - CUTSCENE_SKIP: controlsData?.keys?.CUTSCENE_SKIP ?? null, NOTE_DOWN: controlsData?.keys?.NOTE_DOWN ?? null, NOTE_LEFT: controlsData?.keys?.NOTE_LEFT ?? null, NOTE_RIGHT: controlsData?.keys?.NOTE_RIGHT ?? null, @@ -293,7 +292,6 @@ class SaveDataMigrator ACCEPT: controlsData?.pad?.ACCEPT ?? null, BACK: controlsData?.pad?.BACK ?? null, CUTSCENE_ADVANCE: controlsData?.pad?.CUTSCENE_ADVANCE ?? null, - CUTSCENE_SKIP: controlsData?.pad?.CUTSCENE_SKIP ?? null, NOTE_DOWN: controlsData?.pad?.NOTE_DOWN ?? null, NOTE_LEFT: controlsData?.pad?.NOTE_LEFT ?? null, NOTE_RIGHT: controlsData?.pad?.NOTE_RIGHT ?? null, diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx index 2c8970357..dc742874f 100644 --- a/source/funkin/ui/MusicBeatSubState.hx +++ b/source/funkin/ui/MusicBeatSubState.hx @@ -51,6 +51,7 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler override function update(elapsed:Float):Void { + // 3.59% CPU Usage (100% is FlxTypedGroup#update() and most of that is updating each member.) super.update(elapsed); // Emergency exit button. @@ -61,8 +62,11 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler // Display Conductor info in the watch window. FlxG.watch.addQuick("musicTime", FlxG.sound.music?.time ?? 0.0); + + // 0.09% CPU Usage? Conductor.watchQuick(); + // 4.31% CPU Usage dispatchEvent(new UpdateScriptEvent(elapsed)); } diff --git a/source/funkin/ui/debug/dialogue/ConversationDebugState.hx b/source/funkin/ui/debug/dialogue/ConversationDebugState.hx index 33a6f365a..abda3d3b1 100644 --- a/source/funkin/ui/debug/dialogue/ConversationDebugState.hx +++ b/source/funkin/ui/debug/dialogue/ConversationDebugState.hx @@ -62,15 +62,6 @@ class ConversationDebugState extends MusicBeatState if (conversation != null) { if (controls.CUTSCENE_ADVANCE) conversation.advanceConversation(); - - if (controls.CUTSCENE_SKIP) - { - conversation.trySkipConversation(elapsed); - } - else - { - conversation.trySkipConversation(-1); - } } } } diff --git a/source/funkin/ui/options/ControlsMenu.hx b/source/funkin/ui/options/ControlsMenu.hx index bda071846..62ae4b1a9 100644 --- a/source/funkin/ui/options/ControlsMenu.hx +++ b/source/funkin/ui/options/ControlsMenu.hx @@ -27,7 +27,7 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page static var controlGroups:Array<Array<Control>> = [ [NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT], [UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK], - [CUTSCENE_ADVANCE, CUTSCENE_SKIP], + [CUTSCENE_ADVANCE], [VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE], [DEBUG_MENU, DEBUG_CHART] ]; diff --git a/source/funkin/util/plugins/MemoryGCPlugin.hx b/source/funkin/util/plugins/MemoryGCPlugin.hx new file mode 100644 index 000000000..3df861eb5 --- /dev/null +++ b/source/funkin/util/plugins/MemoryGCPlugin.hx @@ -0,0 +1,37 @@ +package funkin.util.plugins; + +import flixel.FlxBasic; + +/** + * A plugin which adds functionality to press `Ins` to immediately perform memory garbage collection. + */ +class MemoryGCPlugin extends FlxBasic +{ + public function new() + { + super(); + } + + public static function initialize():Void + { + FlxG.plugins.addPlugin(new MemoryGCPlugin()); + } + + public override function update(elapsed:Float):Void + { + super.update(elapsed); + + if (FlxG.keys.justPressed.INSERT) + { + var perfStart:Float = Sys.time(); + funkin.util.MemoryUtil.collect(true); + var perfEnd:Float = Sys.time(); + trace("Memory GC took " + (perfEnd - perfStart) + " seconds"); + } + } + + public override function destroy():Void + { + super.destroy(); + } +} diff --git a/source/funkin/util/tools/FlxTweenTools.hx b/source/funkin/util/tools/FlxTweenTools.hx deleted file mode 100644 index 0860af64b..000000000 --- a/source/funkin/util/tools/FlxTweenTools.hx +++ /dev/null @@ -1,25 +0,0 @@ -package funkin.util.tools; - -import flixel.tweens.FlxTween; -import flixel.tweens.FlxTween.FlxTweenManager; - -class FlxTweenTools -{ - /** - * Tween the background color of a FlxState. - * @param globalManager `flixel.tweens.FlxTween.globalManager` - * @param targetState The FlxState to tween the background color of. - * @param duration The duration of the tween. - * @param fromColor The starting color. - * @param toColor The ending color. - * @param options The options for the tween. - * @return The tween. - */ - public static function bgColor(globalManager:FlxTweenManager, targetState:FlxState, duration:Float = 1.0, fromColor:FlxColor, toColor:FlxColor, - ?options:TweenOptions):BackgroundColorTween - { - var tween = new BackgroundColorTween(options, this); - tween.tween(duration, fromColor, toColor, targetState); - globalManager.add(tween); - } -}