PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/remixtechnology/SWFProfiler.hx

https://code.google.com/p/voxel-editor/
Haxe | 465 lines | 375 code | 65 blank | 25 comment | 34 complexity | 65ced8a93de88fd47973a21f355db091 MD5 | raw file
  1. /**
  2. * original author shanem (Shane McCartney) http://www.lostinactionscript.com/blog/index.php/2008/10/06/as3-swf-profiler/
  3. * ported to haXe by theRemix : http://remixtechnology.com
  4. * demo and source : http://remixtechnology.com/view/SWFProfiler_haXe
  5. *
  6. * Usage: SWFProfiler.init( ?inspector_object_starting_point:Dynamic );
  7. * Right-Click / Command-Click on the stage after SWFProfiler has been initialized.
  8. * Choose "Show Profiler" to open the SWFProfiler
  9. * Choose "Garbage Collector" to force gc().
  10. * if SWFProfiler is visible, choose "Hide Profiler" to remove it from stage.
  11. *
  12. * Initialize without optional parameter: SWFProfiler.init();
  13. * Will disable the Inspector function.
  14. *
  15. * To Enable the Inspector function, pass an object as the starting point to trace from.
  16. * SWFProfiler.init(this);
  17. *
  18. * in the inspector textinput, use standard dot notation starting from the object passed
  19. * "field" or "object.field" or "object.object.field"
  20. *
  21. * the value of the field will display in the inspector value box (right half) if it exists
  22. * the text in the inspector textinput will turn red if the field/object does not exist
  23. *
  24. */
  25. package com.remixtechnology;
  26. import flash.Lib;
  27. import flash.Error;
  28. import flash.display.Stage;
  29. import flash.display.Sprite;
  30. import flash.display.Graphics;
  31. import flash.display.InteractiveObject;
  32. import flash.display.Shape;
  33. import flash.text.TextField;
  34. import flash.text.TextFormat;
  35. import flash.text.TextFieldAutoSize;
  36. import flash.events.Event;
  37. import flash.events.FocusEvent;
  38. import flash.events.ContextMenuEvent;
  39. import flash.events.EventDispatcher;
  40. import flash.net.LocalConnection;
  41. import flash.system.System;
  42. import flash.ui.ContextMenu;
  43. import flash.ui.ContextMenuItem;
  44. import haxe.Timer;
  45. class SWFProfiler {
  46. private static var itvTime : Int;
  47. private static var initTime : Int;
  48. private static var currentTime : Int;
  49. private static var frameCount : Int;
  50. private static var totalCount : Int;
  51. public static var minFps : Int;
  52. public static var maxFps : Int;
  53. public static var minMem : Float;
  54. public static var maxMem : Float;
  55. public static var history : Int = 60;
  56. public static var fpsList : Array<Int> = new Array<Int>();
  57. public static var memList : Array<Float> = new Array<Float>();
  58. public static var displayed : Bool = false;
  59. private static var started : Bool = false;
  60. private static var inited : Bool = false;
  61. private static var frame : Sprite;
  62. private static var stage : Stage;
  63. private static var content : ProfilerContent;
  64. private static var ci : ContextMenuItem;
  65. private static var gc_ci: ContextMenuItem;
  66. public static inline function init(?main = null) : Void {
  67. if(!inited){
  68. inited = true;
  69. stage = Lib.current.stage;
  70. content = new ProfilerContent(main);
  71. frame = new Sprite();
  72. minFps = maxFps = 0;
  73. maxMem = 0;
  74. minMem = currentMem;
  75. var cm : ContextMenu = new ContextMenu();
  76. cm.hideBuiltInItems();
  77. ci = new ContextMenuItem("Show Profiler", true);
  78. ci.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, select_ci, false, 0, true);
  79. gc_ci = new ContextMenuItem("Garbage Collector");
  80. gc_ci.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, select_gc_ci, false, 0, true);
  81. cm.customItems = [ci,gc_ci];
  82. flash.Lib.current.contextMenu = cm;
  83. start();
  84. }
  85. }
  86. public static inline function start() : Void {
  87. if(!started){
  88. started = true;
  89. initTime = itvTime = Std.int(Timer.stamp());
  90. totalCount = frameCount = 0;
  91. frame.addEventListener(Event.ENTER_FRAME, frameLoop, false, 0, true);
  92. }
  93. }
  94. public static inline function stop() : Void {
  95. if(!started){
  96. started = false;
  97. frame.removeEventListener(Event.ENTER_FRAME, frameLoop);
  98. }
  99. }
  100. public static var currentFps:Int;
  101. public static var currentMem(get_currentMem, never):Float;
  102. public static inline function get_currentMem() : Float {
  103. return (System.totalMemory / 1024) / 1000;
  104. }
  105. public static var averageFps(get_averageFps, never):Float;
  106. public static inline function get_averageFps() : Float {
  107. return totalCount / runningTime;
  108. }
  109. public static var runningTime(get_runningTime, never):Float;
  110. private static inline function get_runningTime() : Float {
  111. return (currentTime - initTime) ;
  112. }
  113. public static var intervalTime(get_intervalTime, never):Float;
  114. private static inline function get_intervalTime() : Float {
  115. return (currentTime - itvTime);
  116. }
  117. private static inline function select_ci(_) : Void {
  118. if(!displayed) {
  119. show();
  120. } else {
  121. hide();
  122. }
  123. }
  124. private static inline function select_gc_ci(_) : Void {
  125. System.gc();
  126. System.gc(); // i always see people do it twice
  127. }
  128. private static inline function show() : Void {
  129. ci.caption = "Hide Profiler";
  130. displayed = true;
  131. stage.addEventListener(Event.RESIZE, resize, false, 0, true);
  132. stage.addChild(content);
  133. updateDisplay();
  134. }
  135. private static inline function hide() : Void {
  136. ci.caption = "Show Profiler";
  137. displayed = false;
  138. stage.removeEventListener(Event.RESIZE, resize);
  139. stage.removeChild(content);
  140. }
  141. private static inline function resize(e:Event) : Void {
  142. content.update(runningTime, minFps, maxFps, minMem, maxMem, currentFps, currentMem, averageFps, fpsList, memList, history);
  143. }
  144. private static inline function frameLoop(_) : Void {
  145. currentTime = Std.int(Timer.stamp());
  146. frameCount++;
  147. totalCount++;
  148. if(intervalTime >= 1) {
  149. currentFps = frameCount;
  150. if(displayed) {
  151. updateDisplay();
  152. } else {
  153. updateMinMax();
  154. }
  155. fpsList.push(currentFps);
  156. memList.push(currentMem);
  157. if(fpsList.length > history) fpsList.shift();
  158. if(memList.length > history) memList.shift();
  159. itvTime = currentTime;
  160. frameCount = 0;
  161. }
  162. }
  163. private static inline function updateDisplay() : Void {
  164. updateMinMax();
  165. content.update(runningTime, minFps, maxFps, minMem, maxMem, currentFps, currentMem, averageFps, fpsList, memList, history);
  166. }
  167. private static inline function updateMinMax() : Void {
  168. maxFps = Std.int(Math.max(currentFps, maxFps));
  169. minMem = Math.min(currentMem, minMem);
  170. maxMem = Math.max(currentMem, maxMem);
  171. }
  172. }
  173. class ProfilerContent extends Sprite {
  174. private static inline var FPS_LINE_COLOR_HIGH = 0x33FF00;
  175. private static inline var FPS_LINE_COLOR_NORMAL = 0xFFEE33;//0x0099CC;
  176. private static inline var FPS_LINE_COLOR_LOW = 0xFF3333;
  177. private static inline var MEM_LINE_COLOR_LOW = 0x00CCFF;
  178. private static inline var MEM_LINE_COLOR_NORMAL = 0xFFEE33;//0x336699;
  179. private static inline var MEM_LINE_COLOR_HIGH = 0xFF3366;
  180. private var fpsLabel: TextField;
  181. private var minFpsTxtBx : TextField;
  182. private var maxFpsTxtBx : TextField;
  183. private var minMemTxtBx : TextField;
  184. private var maxMemTxtBx : TextField;
  185. private var memLabel: TextField;
  186. private var infoTxtBx : TextField;
  187. private var inspectLabel : TextField;
  188. private var inspectInputTxt : TextField;
  189. private static inline var exists_tf : TextFormat = new TextFormat("_sans", 9, 0x99CCFF);
  190. private static inline var undefined_tf : TextFormat = new TextFormat("_sans", 9, 0xFF88AA);
  191. private static inline var tf : TextFormat = new TextFormat("_sans", 9, 0xCCCCCC);
  192. private var box : Shape;
  193. private var fps : Shape;
  194. private var mb : Shape;
  195. private var main: Dynamic;
  196. private var boxHeight: Int;
  197. public function new(?_main:Dynamic = null) : Void {
  198. super();
  199. fps = new Shape();
  200. mb = new Shape();
  201. box = new Shape();
  202. main = _main;
  203. //this.mouseChildren = (main==null)?false:true; // not necessary
  204. this.mouseEnabled = false;
  205. fps.x = 65;
  206. fps.y = 45;
  207. mb.x = 65;
  208. mb.y = 90;
  209. boxHeight = (main==null)?100:120;
  210. minFpsTxtBx = new TextField();
  211. minFpsTxtBx.autoSize = TextFieldAutoSize.RIGHT;
  212. minFpsTxtBx.defaultTextFormat = tf;
  213. minFpsTxtBx.x = 60;
  214. minFpsTxtBx.y = 37;
  215. minFpsTxtBx.mouseEnabled = false;
  216. maxFpsTxtBx = new TextField();
  217. maxFpsTxtBx.autoSize = TextFieldAutoSize.RIGHT;
  218. maxFpsTxtBx.defaultTextFormat = tf;
  219. maxFpsTxtBx.x = 60;
  220. maxFpsTxtBx.y = 5;
  221. maxFpsTxtBx.mouseEnabled = false;
  222. fpsLabel = new TextField();
  223. fpsLabel.autoSize = TextFieldAutoSize.RIGHT;
  224. fpsLabel.defaultTextFormat = tf;
  225. fpsLabel.x = 50;
  226. fpsLabel.y = 16;
  227. fpsLabel.mouseEnabled = false;
  228. minMemTxtBx = new TextField();
  229. minMemTxtBx.autoSize = TextFieldAutoSize.RIGHT;
  230. minMemTxtBx.defaultTextFormat = tf;
  231. minMemTxtBx.x = 60;
  232. minMemTxtBx.y = 83;
  233. minMemTxtBx.mouseEnabled = false;
  234. maxMemTxtBx = new TextField();
  235. maxMemTxtBx.autoSize = TextFieldAutoSize.RIGHT;
  236. maxMemTxtBx.defaultTextFormat = tf;
  237. maxMemTxtBx.x = 60;
  238. maxMemTxtBx.y = 50;
  239. maxMemTxtBx.mouseEnabled = false;
  240. memLabel = new TextField();
  241. memLabel.autoSize = TextFieldAutoSize.RIGHT;
  242. memLabel.defaultTextFormat = tf;
  243. memLabel.x = 55;
  244. memLabel.y = 66;
  245. memLabel.mouseEnabled = false;
  246. addChild(box);
  247. addChild(fpsLabel);
  248. addChild(minFpsTxtBx);
  249. addChild(maxFpsTxtBx);
  250. addChild(memLabel);
  251. addChild(minMemTxtBx);
  252. addChild(maxMemTxtBx);
  253. addChild(fps);
  254. addChild(mb);
  255. if(main != null){
  256. infoTxtBx = new TextField();
  257. infoTxtBx.autoSize = TextFieldAutoSize.LEFT;
  258. infoTxtBx.defaultTextFormat = new TextFormat("_sans", 11, 0xCCCCCC);
  259. infoTxtBx.y = 98;
  260. infoTxtBx.x = 290;
  261. infoTxtBx.mouseEnabled = false;
  262. inspectLabel = new TextField();
  263. inspectLabel.autoSize = TextFieldAutoSize.LEFT;
  264. inspectLabel.defaultTextFormat = tf;
  265. inspectLabel.text = "Inspect Object :";
  266. inspectLabel.x = 7;
  267. inspectLabel.y = 98;
  268. inspectLabel.mouseEnabled = false;
  269. inspectInputTxt = new TextField();
  270. inspectInputTxt.type = flash.text.TextFieldType.INPUT;
  271. inspectInputTxt.defaultTextFormat = exists_tf;
  272. inspectInputTxt.text = "stage.frameRate";
  273. inspectInputTxt.x = 80;
  274. inspectInputTxt.y = 98;
  275. inspectInputTxt.width = 200;
  276. inspectInputTxt.height = 18;
  277. inspectInputTxt.mouseEnabled = true;
  278. addChild(infoTxtBx);
  279. addChild(inspectLabel);
  280. addChild(inspectInputTxt);
  281. }
  282. this.addEventListener(Event.ADDED_TO_STAGE, added, false, 0, true);
  283. this.addEventListener(Event.REMOVED_FROM_STAGE, removed, false, 0, true);
  284. }
  285. 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 {
  286. if(runningTime >= 1 && maxMem > 0) {
  287. minFpsTxtBx.text = Std.string(minFps);
  288. maxFpsTxtBx.text = Std.string(maxFps);
  289. minMemTxtBx.text = Std.string(minMem);
  290. maxMemTxtBx.text = Std.string(maxMem);
  291. }
  292. fpsLabel.text = Std.int(currentFps) + " FPS\n" + Std.int(averageFps) + " Avg";
  293. memLabel.text = currentMem + " Mb";
  294. if(main != null) updateInspector();
  295. var vec : Graphics = fps.graphics;
  296. vec.clear();
  297. var i : Int = 0;
  298. var len : Int = fpsList.length;
  299. var height : Int = 35;
  300. var width : Int = stage.stageWidth - 80;
  301. var inc : Float = width / (history - 1);
  302. var rateRange : Float = maxFps - minFps;
  303. var value : Float;
  304. for(i in 0...len) {
  305. value = (fpsList[i] - minFps) / rateRange;
  306. vec.lineStyle(1,
  307. if(value<=.7){
  308. FPS_LINE_COLOR_LOW;
  309. }else if(value>=.9){
  310. FPS_LINE_COLOR_HIGH;
  311. }else{
  312. FPS_LINE_COLOR_NORMAL;
  313. }, 0.7);
  314. if(i == 0) {
  315. vec.moveTo(width- (len-1-i) * inc, -value * height);
  316. } else {
  317. vec.lineTo(width- (len-1-i) * inc, -value * height);
  318. }
  319. }
  320. vec = mb.graphics;
  321. vec.clear();
  322. i = 0;
  323. len = memList.length;
  324. rateRange = maxMem - minMem;
  325. for(i in 0...len) {
  326. value = (memList[i] - minMem) / rateRange;
  327. vec.lineStyle(1,
  328. if(value<=.6){
  329. MEM_LINE_COLOR_LOW;
  330. }else if(value>=.95){
  331. MEM_LINE_COLOR_HIGH;
  332. }else{
  333. MEM_LINE_COLOR_NORMAL;
  334. }, 0.7);
  335. if(i == 0) {
  336. vec.moveTo(width- (len-1-i) * inc, -value * height);
  337. } else {
  338. vec.lineTo(width- (len-1-i) * inc, -value * height);
  339. }
  340. }
  341. }
  342. private inline function updateInspector( ):Void
  343. {
  344. var obj:Dynamic = main;
  345. var obj_ar:Array<String> = inspectInputTxt.text.split(".");
  346. if(inspectInputTxt.text.lastIndexOf(".") > 0){
  347. for(i in 0...obj_ar.length){
  348. if(Reflect.hasField(obj, obj_ar[i])){
  349. if(i < obj_ar.length-1){
  350. inspectInputTxt.defaultTextFormat = exists_tf;
  351. obj = Reflect.field(obj, obj_ar[i]);
  352. }else{
  353. if(Reflect.hasField(obj, obj_ar[i])){
  354. inspectInputTxt.defaultTextFormat = exists_tf;
  355. infoTxtBx.text = Reflect.field(obj, obj_ar[i]);
  356. }
  357. }
  358. inspectInputTxt.text = inspectInputTxt.text;
  359. }else{
  360. inspectInputTxt.defaultTextFormat = undefined_tf;
  361. infoTxtBx.text = "";
  362. inspectInputTxt.text = inspectInputTxt.text;
  363. break;
  364. }
  365. }
  366. }else{
  367. if(Reflect.hasField(main,inspectInputTxt.text)){
  368. infoTxtBx.text = Reflect.field(main, inspectInputTxt.text);
  369. inspectInputTxt.defaultTextFormat = exists_tf;
  370. }else{
  371. inspectInputTxt.defaultTextFormat = undefined_tf;
  372. infoTxtBx.text = "";
  373. }
  374. inspectInputTxt.text = inspectInputTxt.text;
  375. }
  376. }
  377. private inline function added(e : Event) : Void {
  378. resize();
  379. stage.addEventListener(Event.RESIZE, resize, false, 0, true);
  380. }
  381. private inline function removed(e : Event) : Void {
  382. stage.removeEventListener(Event.RESIZE, resize);
  383. }
  384. private inline function resize(e : Event = null) : Void {
  385. var vec : Graphics = box.graphics;
  386. vec.clear();
  387. vec.beginFill(0x000000, 0.7);
  388. vec.drawRect(0, 0, stage.stageWidth, boxHeight);
  389. vec.lineStyle(1, 0xFFFFFF, 0.5);
  390. vec.moveTo(65, 45);
  391. vec.lineTo(65, 10);
  392. vec.moveTo(65, 45);
  393. vec.lineTo(stage.stageWidth - 15, 45);
  394. vec.moveTo(65, 90);
  395. vec.lineTo(65, 55);
  396. vec.moveTo(65, 90);
  397. vec.lineTo(stage.stageWidth - 15, 90);
  398. vec.endFill();
  399. }
  400. }