/src/remixtechnology/SWFProfiler.hx
Haxe | 465 lines | 375 code | 65 blank | 25 comment | 34 complexity | 65ced8a93de88fd47973a21f355db091 MD5 | raw file
- /**
- * original author shanem (Shane McCartney) http://www.lostinactionscript.com/blog/index.php/2008/10/06/as3-swf-profiler/
- * ported to haXe by theRemix : http://remixtechnology.com
- * demo and source : http://remixtechnology.com/view/SWFProfiler_haXe
- *
- * Usage: SWFProfiler.init( ?inspector_object_starting_point:Dynamic );
- * Right-Click / Command-Click on the stage after SWFProfiler has been initialized.
- * Choose "Show Profiler" to open the SWFProfiler
- * Choose "Garbage Collector" to force gc().
- * if SWFProfiler is visible, choose "Hide Profiler" to remove it from stage.
- *
- * Initialize without optional parameter: SWFProfiler.init();
- * Will disable the Inspector function.
- *
- * To Enable the Inspector function, pass an object as the starting point to trace from.
- * SWFProfiler.init(this);
- *
- * in the inspector textinput, use standard dot notation starting from the object passed
- * "field" or "object.field" or "object.object.field"
- *
- * the value of the field will display in the inspector value box (right half) if it exists
- * the text in the inspector textinput will turn red if the field/object does not exist
- *
- */
-
- package com.remixtechnology;
- import flash.Lib;
- import flash.Error;
- import flash.display.Stage;
- import flash.display.Sprite;
- import flash.display.Graphics;
- import flash.display.InteractiveObject;
- import flash.display.Shape;
- import flash.text.TextField;
- import flash.text.TextFormat;
- import flash.text.TextFieldAutoSize;
- import flash.events.Event;
- import flash.events.FocusEvent;
- import flash.events.ContextMenuEvent;
- import flash.events.EventDispatcher;
- import flash.net.LocalConnection;
- import flash.system.System;
- import flash.ui.ContextMenu;
- import flash.ui.ContextMenuItem;
- import haxe.Timer;
-
- class SWFProfiler {
- private static var itvTime : Int;
- private static var initTime : Int;
- private static var currentTime : Int;
- private static var frameCount : Int;
- private static var totalCount : Int;
-
- public static var minFps : Int;
- public static var maxFps : Int;
- public static var minMem : Float;
- public static var maxMem : Float;
- public static var history : Int = 60;
- public static var fpsList : Array<Int> = new Array<Int>();
- public static var memList : Array<Float> = new Array<Float>();
-
- public static var displayed : Bool = false;
- private static var started : Bool = false;
- private static var inited : Bool = false;
- private static var frame : Sprite;
- private static var stage : Stage;
- private static var content : ProfilerContent;
- private static var ci : ContextMenuItem;
- private static var gc_ci: ContextMenuItem;
-
- public static inline function init(?main = null) : Void {
- if(!inited){
- inited = true;
- stage = Lib.current.stage;
- content = new ProfilerContent(main);
- frame = new Sprite();
- minFps = maxFps = 0;
- maxMem = 0;
- minMem = currentMem;
-
- var cm : ContextMenu = new ContextMenu();
- cm.hideBuiltInItems();
- ci = new ContextMenuItem("Show Profiler", true);
- ci.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, select_ci, false, 0, true);
- gc_ci = new ContextMenuItem("Garbage Collector");
- gc_ci.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, select_gc_ci, false, 0, true);
- cm.customItems = [ci,gc_ci];
- flash.Lib.current.contextMenu = cm;
-
- start();
- }
- }
-
- public static inline function start() : Void {
- if(!started){
- started = true;
- initTime = itvTime = Std.int(Timer.stamp());
- totalCount = frameCount = 0;
- frame.addEventListener(Event.ENTER_FRAME, frameLoop, false, 0, true);
- }
- }
-
- public static inline function stop() : Void {
- if(!started){
- started = false;
- frame.removeEventListener(Event.ENTER_FRAME, frameLoop);
- }
- }
-
- public static var currentFps:Int;
-
- public static var currentMem(get_currentMem, never):Float;
- public static inline function get_currentMem() : Float {
- return (System.totalMemory / 1024) / 1000;
- }
-
- public static var averageFps(get_averageFps, never):Float;
- public static inline function get_averageFps() : Float {
- return totalCount / runningTime;
- }
-
- public static var runningTime(get_runningTime, never):Float;
- private static inline function get_runningTime() : Float {
- return (currentTime - initTime) ;
- }
-
- public static var intervalTime(get_intervalTime, never):Float;
- private static inline function get_intervalTime() : Float {
- return (currentTime - itvTime);
- }
-
-
- private static inline function select_ci(_) : Void {
- if(!displayed) {
- show();
- } else {
- hide();
- }
- }
-
- private static inline function select_gc_ci(_) : Void {
- System.gc();
- System.gc(); // i always see people do it twice
- }
-
- private static inline function show() : Void {
- ci.caption = "Hide Profiler";
- displayed = true;
- stage.addEventListener(Event.RESIZE, resize, false, 0, true);
- stage.addChild(content);
- updateDisplay();
- }
-
- private static inline function hide() : Void {
- ci.caption = "Show Profiler";
- displayed = false;
- stage.removeEventListener(Event.RESIZE, resize);
- stage.removeChild(content);
- }
-
- private static inline function resize(e:Event) : Void {
- content.update(runningTime, minFps, maxFps, minMem, maxMem, currentFps, currentMem, averageFps, fpsList, memList, history);
- }
-
- private static inline function frameLoop(_) : Void {
- currentTime = Std.int(Timer.stamp());
- frameCount++;
- totalCount++;
-
- if(intervalTime >= 1) {
- currentFps = frameCount;
-
- if(displayed) {
- updateDisplay();
- } else {
- updateMinMax();
- }
- fpsList.push(currentFps);
- memList.push(currentMem);
-
- if(fpsList.length > history) fpsList.shift();
- if(memList.length > history) memList.shift();
-
- itvTime = currentTime;
- frameCount = 0;
- }
- }
-
- private static inline function updateDisplay() : Void {
- updateMinMax();
- content.update(runningTime, minFps, maxFps, minMem, maxMem, currentFps, currentMem, averageFps, fpsList, memList, history);
- }
-
- private static inline function updateMinMax() : Void {
- maxFps = Std.int(Math.max(currentFps, maxFps));
-
- minMem = Math.min(currentMem, minMem);
- maxMem = Math.max(currentMem, maxMem);
- }
- }
-
-
- class ProfilerContent extends Sprite {
-
- private static inline var FPS_LINE_COLOR_HIGH = 0x33FF00;
- private static inline var FPS_LINE_COLOR_NORMAL = 0xFFEE33;//0x0099CC;
- private static inline var FPS_LINE_COLOR_LOW = 0xFF3333;
- private static inline var MEM_LINE_COLOR_LOW = 0x00CCFF;
- private static inline var MEM_LINE_COLOR_NORMAL = 0xFFEE33;//0x336699;
- private static inline var MEM_LINE_COLOR_HIGH = 0xFF3366;
-
- private var fpsLabel: TextField;
- private var minFpsTxtBx : TextField;
- private var maxFpsTxtBx : TextField;
- private var minMemTxtBx : TextField;
- private var maxMemTxtBx : TextField;
- private var memLabel: TextField;
- private var infoTxtBx : TextField;
- private var inspectLabel : TextField;
- private var inspectInputTxt : TextField;
- private static inline var exists_tf : TextFormat = new TextFormat("_sans", 9, 0x99CCFF);
- private static inline var undefined_tf : TextFormat = new TextFormat("_sans", 9, 0xFF88AA);
- private static inline var tf : TextFormat = new TextFormat("_sans", 9, 0xCCCCCC);
- private var box : Shape;
- private var fps : Shape;
- private var mb : Shape;
- private var main: Dynamic;
- private var boxHeight: Int;
-
- public function new(?_main:Dynamic = null) : Void {
- super();
- fps = new Shape();
- mb = new Shape();
- box = new Shape();
- main = _main;
-
- //this.mouseChildren = (main==null)?false:true; // not necessary
- this.mouseEnabled = false;
-
- fps.x = 65;
- fps.y = 45;
- mb.x = 65;
- mb.y = 90;
- boxHeight = (main==null)?100:120;
-
- minFpsTxtBx = new TextField();
- minFpsTxtBx.autoSize = TextFieldAutoSize.RIGHT;
- minFpsTxtBx.defaultTextFormat = tf;
- minFpsTxtBx.x = 60;
- minFpsTxtBx.y = 37;
- minFpsTxtBx.mouseEnabled = false;
-
- maxFpsTxtBx = new TextField();
- maxFpsTxtBx.autoSize = TextFieldAutoSize.RIGHT;
- maxFpsTxtBx.defaultTextFormat = tf;
- maxFpsTxtBx.x = 60;
- maxFpsTxtBx.y = 5;
- maxFpsTxtBx.mouseEnabled = false;
-
- fpsLabel = new TextField();
- fpsLabel.autoSize = TextFieldAutoSize.RIGHT;
- fpsLabel.defaultTextFormat = tf;
- fpsLabel.x = 50;
- fpsLabel.y = 16;
- fpsLabel.mouseEnabled = false;
-
- minMemTxtBx = new TextField();
- minMemTxtBx.autoSize = TextFieldAutoSize.RIGHT;
- minMemTxtBx.defaultTextFormat = tf;
- minMemTxtBx.x = 60;
- minMemTxtBx.y = 83;
- minMemTxtBx.mouseEnabled = false;
-
- maxMemTxtBx = new TextField();
- maxMemTxtBx.autoSize = TextFieldAutoSize.RIGHT;
- maxMemTxtBx.defaultTextFormat = tf;
- maxMemTxtBx.x = 60;
- maxMemTxtBx.y = 50;
- maxMemTxtBx.mouseEnabled = false;
-
- memLabel = new TextField();
- memLabel.autoSize = TextFieldAutoSize.RIGHT;
- memLabel.defaultTextFormat = tf;
- memLabel.x = 55;
- memLabel.y = 66;
- memLabel.mouseEnabled = false;
-
- addChild(box);
- addChild(fpsLabel);
- addChild(minFpsTxtBx);
- addChild(maxFpsTxtBx);
- addChild(memLabel);
- addChild(minMemTxtBx);
- addChild(maxMemTxtBx);
- addChild(fps);
- addChild(mb);
-
- if(main != null){
- infoTxtBx = new TextField();
- infoTxtBx.autoSize = TextFieldAutoSize.LEFT;
- infoTxtBx.defaultTextFormat = new TextFormat("_sans", 11, 0xCCCCCC);
- infoTxtBx.y = 98;
- infoTxtBx.x = 290;
- infoTxtBx.mouseEnabled = false;
-
- inspectLabel = new TextField();
- inspectLabel.autoSize = TextFieldAutoSize.LEFT;
- inspectLabel.defaultTextFormat = tf;
- inspectLabel.text = "Inspect Object :";
- inspectLabel.x = 7;
- inspectLabel.y = 98;
- inspectLabel.mouseEnabled = false;
-
- inspectInputTxt = new TextField();
- inspectInputTxt.type = flash.text.TextFieldType.INPUT;
- inspectInputTxt.defaultTextFormat = exists_tf;
- inspectInputTxt.text = "stage.frameRate";
- inspectInputTxt.x = 80;
- inspectInputTxt.y = 98;
- inspectInputTxt.width = 200;
- inspectInputTxt.height = 18;
- inspectInputTxt.mouseEnabled = true;
-
- addChild(infoTxtBx);
- addChild(inspectLabel);
- addChild(inspectInputTxt);
- }
-
- this.addEventListener(Event.ADDED_TO_STAGE, added, false, 0, true);
- this.addEventListener(Event.REMOVED_FROM_STAGE, removed, false, 0, true);
- }
-
- public inline function update(runningTime : Float, minFps : Int, maxFps : Int, minMem : Float, maxMem : Float, currentFps : Int, currentMem : Float, averageFps : Float, fpsList : Array<Int>, memList : Array<Float>, history : Int) : Void {
- if(runningTime >= 1 && maxMem > 0) {
- minFpsTxtBx.text = Std.string(minFps);
- maxFpsTxtBx.text = Std.string(maxFps);
- minMemTxtBx.text = Std.string(minMem);
- maxMemTxtBx.text = Std.string(maxMem);
- }
-
- fpsLabel.text = Std.int(currentFps) + " FPS\n" + Std.int(averageFps) + " Avg";
- memLabel.text = currentMem + " Mb";
-
- if(main != null) updateInspector();
-
- var vec : Graphics = fps.graphics;
- vec.clear();
-
- var i : Int = 0;
- var len : Int = fpsList.length;
- var height : Int = 35;
- var width : Int = stage.stageWidth - 80;
- var inc : Float = width / (history - 1);
- var rateRange : Float = maxFps - minFps;
- var value : Float;
-
- for(i in 0...len) {
- value = (fpsList[i] - minFps) / rateRange;
- vec.lineStyle(1,
- if(value<=.7){
- FPS_LINE_COLOR_LOW;
- }else if(value>=.9){
- FPS_LINE_COLOR_HIGH;
- }else{
- FPS_LINE_COLOR_NORMAL;
- }, 0.7);
- if(i == 0) {
- vec.moveTo(width- (len-1-i) * inc, -value * height);
- } else {
- vec.lineTo(width- (len-1-i) * inc, -value * height);
- }
- }
-
- vec = mb.graphics;
- vec.clear();
-
- i = 0;
- len = memList.length;
- rateRange = maxMem - minMem;
- for(i in 0...len) {
- value = (memList[i] - minMem) / rateRange;
- vec.lineStyle(1,
- if(value<=.6){
- MEM_LINE_COLOR_LOW;
- }else if(value>=.95){
- MEM_LINE_COLOR_HIGH;
- }else{
- MEM_LINE_COLOR_NORMAL;
- }, 0.7);
- if(i == 0) {
- vec.moveTo(width- (len-1-i) * inc, -value * height);
- } else {
- vec.lineTo(width- (len-1-i) * inc, -value * height);
- }
- }
- }
-
- private inline function updateInspector( ):Void
- {
- var obj:Dynamic = main;
- var obj_ar:Array<String> = inspectInputTxt.text.split(".");
-
- if(inspectInputTxt.text.lastIndexOf(".") > 0){
- for(i in 0...obj_ar.length){
- if(Reflect.hasField(obj, obj_ar[i])){
- if(i < obj_ar.length-1){
- inspectInputTxt.defaultTextFormat = exists_tf;
- obj = Reflect.field(obj, obj_ar[i]);
- }else{
- if(Reflect.hasField(obj, obj_ar[i])){
- inspectInputTxt.defaultTextFormat = exists_tf;
- infoTxtBx.text = Reflect.field(obj, obj_ar[i]);
- }
- }
- inspectInputTxt.text = inspectInputTxt.text;
- }else{
- inspectInputTxt.defaultTextFormat = undefined_tf;
- infoTxtBx.text = "";
- inspectInputTxt.text = inspectInputTxt.text;
- break;
- }
- }
- }else{
- if(Reflect.hasField(main,inspectInputTxt.text)){
- infoTxtBx.text = Reflect.field(main, inspectInputTxt.text);
- inspectInputTxt.defaultTextFormat = exists_tf;
- }else{
- inspectInputTxt.defaultTextFormat = undefined_tf;
- infoTxtBx.text = "";
- }
- inspectInputTxt.text = inspectInputTxt.text;
- }
-
- }
-
- private inline function added(e : Event) : Void {
- resize();
- stage.addEventListener(Event.RESIZE, resize, false, 0, true);
- }
-
- private inline function removed(e : Event) : Void {
- stage.removeEventListener(Event.RESIZE, resize);
- }
-
- private inline function resize(e : Event = null) : Void {
- var vec : Graphics = box.graphics;
- vec.clear();
-
- vec.beginFill(0x000000, 0.7);
- vec.drawRect(0, 0, stage.stageWidth, boxHeight);
- vec.lineStyle(1, 0xFFFFFF, 0.5);
-
- vec.moveTo(65, 45);
- vec.lineTo(65, 10);
- vec.moveTo(65, 45);
- vec.lineTo(stage.stageWidth - 15, 45);
-
- vec.moveTo(65, 90);
- vec.lineTo(65, 55);
- vec.moveTo(65, 90);
- vec.lineTo(stage.stageWidth - 15, 90);
-
- vec.endFill();
- }
- }