diff --git a/source/Main.hx b/source/Main.hx index b7b34afaf..15c7f23aa 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -6,13 +6,12 @@ import flixel.FlxState; import funkin.ui.FullScreenScaleMode; import funkin.Preferences; import funkin.util.logging.CrashHandler; -import funkin.ui.debug.MemoryCounter; +import funkin.ui.debug.FunkinCounter; import funkin.save.Save; import haxe.ui.Toolkit; #if hxvlc import hxvlc.util.Handle; #end -import openfl.display.FPS; import openfl.display.Sprite; import openfl.events.Event; import openfl.Lib; @@ -90,25 +89,14 @@ class Main extends Sprite /** * A frame counter displayed at the top left. */ - public static var fpsCounter:FPS; - - /** - * A RAM counter displayed at the top left. - */ - public static var memoryCounter:MemoryCounter; + public static var funkinCounter:FunkinCounter; function setupGame():Void { initHaxeUI(); // addChild gets called by the user settings code. - fpsCounter = new FPS(10, 3, 0xFFFFFF); - - #if !html5 - // addChild gets called by the user settings code. - // TODO: disabled on HTML5 (todo: find another method that works?) - memoryCounter = new MemoryCounter(10, 13, 0xFFFFFF); - #end + funkinCounter = new FunkinCounter(10, 3, 0xFFFFFF); #if mobile // Add this signal so we can reposition and resize the memory and fps counter. @@ -200,41 +188,23 @@ class Main extends Sprite scale = Math.min(scale, 1); #end final thypos:Float = Math.max(FullScreenScaleMode.notchSize.x, 10); - if (fpsCounter != null) + + if (funkinCounter != null) { - fpsCounter.scaleX = fpsCounter.scaleY = scale; + funkinCounter.scaleX = funkinCounter.scaleY = scale; if (FlxG.game != null) { if (lerp) { - fpsCounter.x = flixel.math.FlxMath.lerp(fpsCounter.x, FlxG.game.x + thypos, FlxG.elapsed * 3); + funkinCounter.x = flixel.math.FlxMath.lerp(funkinCounter.x, FlxG.game.x + thypos, FlxG.elapsed * 3); } else { - fpsCounter.x = FlxG.game.x + FullScreenScaleMode.notchSize.x + 10; + funkinCounter.x = FlxG.game.x + FullScreenScaleMode.notchSize.x + 10; } - fpsCounter.y = FlxG.game.y + (3 * scale); - } - } - - if (memoryCounter != null) - { - memoryCounter.scaleX = memoryCounter.scaleY = scale; - - if (FlxG.game != null) - { - if (lerp) - { - memoryCounter.x = flixel.math.FlxMath.lerp(memoryCounter.x, FlxG.game.x + thypos, FlxG.elapsed * 3); - } - else - { - memoryCounter.x = FlxG.game.x + FullScreenScaleMode.notchSize.x + 10; - } - - memoryCounter.y = FlxG.game.y + (13 * scale); + funkinCounter.y = FlxG.game.y + (3 * scale); } } } diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx index 8be815e1a..8ceff9d1f 100644 --- a/source/funkin/Preferences.hx +++ b/source/funkin/Preferences.hx @@ -486,20 +486,12 @@ class Preferences if (show) { // Enable the debug display. - FlxG.game.parent.addChild(Main.fpsCounter); - - #if !html5 - FlxG.game.parent.addChild(Main.memoryCounter); - #end + FlxG.game.parent.addChild(Main.funkinCounter); } else { // Disable the debug display. - FlxG.game.parent.removeChild(Main.fpsCounter); - - #if !html5 - FlxG.game.parent.removeChild(Main.memoryCounter); - #end + FlxG.game.parent.removeChild(Main.funkinCounter); } } diff --git a/source/funkin/ui/debug/FunkinCounter.hx b/source/funkin/ui/debug/FunkinCounter.hx new file mode 100644 index 000000000..3f98d7267 --- /dev/null +++ b/source/funkin/ui/debug/FunkinCounter.hx @@ -0,0 +1,119 @@ +package funkin.ui.debug; + +import haxe.Timer; +import openfl.display.Sprite; +import openfl.text.TextField; +import openfl.text.TextFormat; +import funkin.util.MemoryUtil; + +class FunkinCounter extends Sprite +{ + static final FPS_UPDATE_DELAY:Int = 200; + static final BYTES_PER_MEG:Float = 1024 * 1024; + static final ROUND_TO:Float = 1 / 100; + + /** + The current frame rate, expressed using frames-per-second. + **/ + @:noCompletion + private var currentFPS(default, null):Int = 0; + + /** + The average frame rate. + **/ + @:noCompletion + private var averageFPS(default, null):Int = 0; + + /** + The lowest frame rate. + **/ + @:noCompletion + private var onePercFPS(default, null):Int = 0; + + /** + The peak of memory usage. + **/ + @:noCompletion + private var memPeak:Float = 0; + + @:noCompletion + private var times:Array = []; + + @:noCompletion + private var fpsValues:Array = []; + + @:noCompletion + private var deltaTimeout:Float = 0; + + @:noCompletion + private var frameCount:Int = 0; + + public var textDisplay:TextField; + + public function new(x:Float = 10, y:Float = 10, color:Int = 0x000000) + { + super(); + + this.x = x; + this.y = y; + + textDisplay = new TextField(); + textDisplay.width = 500; + textDisplay.selectable = false; + textDisplay.mouseEnabled = false; + textDisplay.defaultTextFormat = new TextFormat("_sans", 12, color); + textDisplay.text = ""; + addChild(textDisplay); + } + + @:noCompletion + private override function __enterFrame(deltaTime:Float):Void + { + final currentTime:Float = Timer.stamp() * 1000; + + times.push(currentTime); + + frameCount++; + + while (times[0] < currentTime - 1000) + times.shift(); + + if (deltaTimeout < FPS_UPDATE_DELAY) + { + deltaTimeout += deltaTime; + return; + } + + currentFPS = times.length; + + averageFPS = Math.floor(frameCount / currentTime * 1000); + + if (onePercFPS < times.length / 10) + { + onePercFPS = currentFPS; + } + else if (onePercFPS > currentFPS) + { + onePercFPS = currentFPS; + } + + updateDisplay(); + + deltaTimeout = 0.0; + } + + private function updateDisplay():Void + { + textDisplay.text = "FPS: " + currentFPS; + textDisplay.text += "\nAVG FPS: " + averageFPS; + textDisplay.text += "\n1% LOW FPS: " + onePercFPS; + + #if !html5 + var mem:Float = Math.fround(MemoryUtil.getMemoryUsed() / BYTES_PER_MEG / ROUND_TO) * ROUND_TO; + + if (mem > memPeak) memPeak = mem; + + textDisplay.text += '\nRAM: ${mem}mb / ${memPeak}mb'; + #end + } +} diff --git a/source/funkin/ui/debug/MemoryCounter.hx b/source/funkin/ui/debug/MemoryCounter.hx deleted file mode 100644 index 18b3961b9..000000000 --- a/source/funkin/ui/debug/MemoryCounter.hx +++ /dev/null @@ -1,44 +0,0 @@ -package funkin.ui.debug; - -import funkin.util.MemoryUtil; -import openfl.text.TextFormat; -import openfl.text.TextField; - -class MemoryCounter extends TextField -{ - var memPeak:Float = 0; - - static final BYTES_PER_MEG:Float = 1024 * 1024; - static final ROUND_TO:Float = 1 / 100; - - public function new(x:Float = 10, y:Float = 10, color:Int = 0x000000) - { - super(); - - this.x = x; - this.y = y; - this.width = 500; - this.selectable = false; - this.mouseEnabled = false; - defaultTextFormat = new TextFormat("_sans", 12, color); - text = "RAM: "; - - #if flash - addEventListener(Event.ENTER_FRAME, function(e) { - var time = Lib.getTimer(); - __enterFrame(time - currentTime); - }); - #end - } - - // Event Handlers - @:noCompletion - #if !flash override #end function __enterFrame(deltaTime:Float):Void - { - var mem:Float = Math.fround(MemoryUtil.getMemoryUsed() / BYTES_PER_MEG / ROUND_TO) * ROUND_TO; - - if (mem > memPeak) memPeak = mem; - - text = 'RAM: ${mem}mb / ${memPeak}mb'; - } -}