From ddfb0c6a61fe445a880229fda99b8c2c6700d662 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 22 Feb 2024 23:37:52 -0500 Subject: [PATCH] Working on more asset caching improvements. --- source/funkin/graphics/FunkinSprite.hx | 61 +++++++++++++++++++ source/funkin/play/components/PopUpStuff.hx | 9 ++- source/funkin/ui/transition/LoadingState.hx | 26 +++++++- .../funkin/ui/transition/StickerSubState.hx | 5 +- 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/source/funkin/graphics/FunkinSprite.hx b/source/funkin/graphics/FunkinSprite.hx index 6c8ce1308..f47b4138a 100644 --- a/source/funkin/graphics/FunkinSprite.hx +++ b/source/funkin/graphics/FunkinSprite.hx @@ -11,6 +11,18 @@ import flixel.graphics.FlxGraphic; */ class FunkinSprite extends FlxSprite { + /** + * An internal list of all the textures cached with `cacheTexture`. + * This excludes any temporary textures like those from `FlxText` or `makeSolidColor`. + */ + static var currentCachedTextures:Map = []; + + /** + * An internal list of textures that were cached in the previous state. + * We don't know whether we want to keep them cached or not. + */ + static var previousCachedTextures:Map = []; + /** * @param x Starting X position * @param y Starting Y position @@ -113,6 +125,19 @@ class FunkinSprite extends FlxSprite public static function cacheTexture(key:String):Void { + // We don't want to cache the same texture twice. + if (currentCachedTextures.exists(key)) return; + + if (previousCachedTextures.exists(key)) + { + // Move the graphic from the previous cache to the current cache. + var graphic = previousCachedTextures.get(key); + previousCachedTextures.remove(key); + currentCachedTextures.set(key, graphic); + return; + } + + // Else, texture is currently uncached. var graphic = flixel.graphics.FlxGraphic.fromAssetKey(key, false, null, true); if (graphic == null) { @@ -121,6 +146,8 @@ class FunkinSprite extends FlxSprite else { trace('Successfully cached graphic: $key'); + graphic.persist = true; + currentCachedTextures.set(key, graphic); } } @@ -134,6 +161,40 @@ class FunkinSprite extends FlxSprite cacheTexture(Paths.image(key)); } + /** + * Call this, then `cacheTexture` to keep the textures we still need, then `purgeCache` to remove the textures that we won't be using anymore. + */ + public static function preparePurgeCache():Void + { + previousCachedTextures = currentCachedTextures; + currentCachedTextures = []; + } + + public static function purgeCache():Void + { + // Everything that is in previousCachedTextures but not in currentCachedTextures should be destroyed. + for (graphicKey in previousCachedTextures.keys()) + { + var graphic = previousCachedTextures.get(graphicKey); + FlxG.bitmap.remove(graphic); + graphic.destroy(); + previousCachedTextures.remove(graphicKey); + } + } + + static function isGraphicCached(graphic:FlxGraphic):Bool + { + if (graphic == null) return false; + var result = FlxG.bitmap.get(graphic.key); + if (result == null) return false; + if (result != graphic) + { + FlxG.log.warn('Cached graphic does not match original: ${graphic.key}'); + return false; + } + return true; + } + /** * Acts similarly to `makeGraphic`, but with improved memory usage, * at the expense of not being able to paint onto the resulting sprite. diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 593a7333e..88ffa468c 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -15,7 +15,9 @@ class PopUpStuff extends FlxTypedGroup public function displayRating(daRating:String) { + #if sys var perfStart:Float = Sys.time(); + #end if (daRating == null) daRating = "good"; @@ -64,14 +66,17 @@ class PopUpStuff extends FlxTypedGroup startDelay: Conductor.instance.beatLengthMs * 0.001 }); + #if sys var perfEnd:Float = Sys.time(); - trace("displayRating took: " + (perfEnd - perfStart)); + #end } public function displayCombo(?combo:Int = 0):Int { + #if sys var perfStart:Float = Sys.time(); + #end if (combo == null) combo = 0; @@ -170,8 +175,10 @@ class PopUpStuff extends FlxTypedGroup daLoop++; } + #if sys var perfEnd:Float = Sys.time(); trace("displayCombo took: " + (perfEnd - perfStart)); + #end return combo; } diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index e893b0cec..3a41340a6 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -3,6 +3,7 @@ package funkin.ui.transition; import flixel.FlxSprite; import flixel.math.FlxMath; import flixel.tweens.FlxEase; +import funkin.graphics.FunkinSprite; import flixel.tweens.FlxTween; import flixel.util.FlxTimer; import funkin.graphics.shaders.ScreenWipeShader; @@ -208,10 +209,31 @@ class LoadingState extends MusicBeatState params.targetSong.cacheCharts(true); } - // TODO: This is a hack! Redo this later when we have a proper asset caching system. + // TODO: This section is a hack! Redo this later when we have a proper asset caching system. + FunkinSprite.preparePurgeCache(); FunkinSprite.cacheTexture(Paths.image('combo')); FunkinSprite.cacheTexture(Paths.image('healthBar')); FunkinSprite.cacheTexture(Paths.image('menuDesat')); + FunkinSprite.cacheTexture(Paths.image('combo')); + FunkinSprite.cacheTexture(Paths.image('num0')); + FunkinSprite.cacheTexture(Paths.image('num1')); + FunkinSprite.cacheTexture(Paths.image('num2')); + FunkinSprite.cacheTexture(Paths.image('num3')); + FunkinSprite.cacheTexture(Paths.image('num4')); + FunkinSprite.cacheTexture(Paths.image('num5')); + FunkinSprite.cacheTexture(Paths.image('num6')); + FunkinSprite.cacheTexture(Paths.image('num7')); + FunkinSprite.cacheTexture(Paths.image('num8')); + FunkinSprite.cacheTexture(Paths.image('num9')); + FunkinSprite.cacheTexture(Paths.image('ready', 'shared')); + FunkinSprite.cacheTexture(Paths.image('set', 'shared')); + FunkinSprite.cacheTexture(Paths.image('go', 'shared')); + FunkinSprite.cacheTexture(Paths.image('sick', 'shared')); + FunkinSprite.cacheTexture(Paths.image('good', 'shared')); + FunkinSprite.cacheTexture(Paths.image('bad', 'shared')); + FunkinSprite.cacheTexture(Paths.image('shit', 'shared')); + FunkinSprite.cacheTexture(Paths.image('miss', 'shared')); // TODO: Remove + FunkinSprite.purgeCache(); FlxG.switchState(playStateCtor); #end @@ -358,7 +380,7 @@ class MultiCallback public static function coolSwitchState(state:NextState, transitionTex:String = "shaderTransitionStuff/coolDots", time:Float = 2) { - var screenShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("shaderTransitionStuff/coolDots")); + var screenShit:FunkinSprite = FunkinSprite.create(Paths.image("shaderTransitionStuff/coolDots")); var screenWipeShit:ScreenWipeShader = new ScreenWipeShader(); screenWipeShit.funnyShit.input = screenShit.pixels; diff --git a/source/funkin/ui/transition/StickerSubState.hx b/source/funkin/ui/transition/StickerSubState.hx index e94eed7d5..fda7d1d5d 100644 --- a/source/funkin/ui/transition/StickerSubState.hx +++ b/source/funkin/ui/transition/StickerSubState.hx @@ -3,6 +3,7 @@ package funkin.ui.transition; import flixel.FlxSprite; import haxe.Json; import lime.utils.Assets; +import funkin.graphics.FunkinSprite; // import flxtyped group import funkin.ui.MusicBeatSubState; import funkin.ui.story.StoryMenuState; @@ -301,14 +302,14 @@ class StickerSubState extends MusicBeatSubState } } -class StickerSprite extends FlxSprite +class StickerSprite extends FunkinSprite { public var timing:Float = 0; public function new(x:Float, y:Float, stickerSet:String, stickerName:String):Void { super(x, y); - loadGraphic(Paths.image('transitionSwag/' + stickerSet + '/' + stickerName)); + loadTexture(Paths.image('transitionSwag/' + stickerSet + '/' + stickerName)); updateHitbox(); scrollFactor.set(); }