actionscript-3remote-debuggingstarling-framework

As3 Monster Debugger In Starling FrameWork


As flash professional does not have support of flash player 11 while testing project with ctrl+Enter, I can only test flash projects in browser so I can't use trace to check things working, and I can't event integrate monster debugger in starling object, it does not trace anything. Does someone have solution for this, I mean how can I test flash project in browser?


Solution

  • You can use the Firebug or Google Chrome's console for debugging. I made the following class for this purpose. Just call Log.info(), or Log.dump() to output statements directly to the browser's console.

    package {
    
        import flash.external.ExternalInterface;
        import flash.utils.describeType;
        import flash.utils.Dictionary;
        import flash.display.Sprite;
        import flash.text.TextFormat;
        import flash.text.TextField;
    
    
        public class Log {
    
            // USAGE:
            //
            // Log.info(anything)
            // Log.warning(anything)
            // Log.error(anything)
            // Log.dump(anything)
            //
            // Logged object will appear in both the trace window and in the Firebug console (if it's enabled)
    
    
            static public var enabled:Boolean = true;
            static private var prefix_:String = null;
            static private var logWindow_:Sprite;
            static private var logWindowHeight_:Number;
            static private var logTextField_:TextField;
            static private var closeLogWindowButton_:TextField;
            static private var logWindowMaximized_:Boolean = false;
            static private var outputTextField_:TextField = null;
    
    
            static public function get outputTextField():TextField {
                return outputTextField_;
            }
    
    
            static public function set outputTextField(v:TextField):void {
                if (outputTextField_ === v) return;
                outputTextField_ = v;
            }
    
    
            static private function log(s:*, type:String = null, param:* = null):void {
                if (!enabled) return;
    
                var logString:String = String(s);
                var serializedObject:* = null;
                var serializedObjectString:String = null;
    
                if (type == "Dump") {
                    serializedObject = serializeObject_(s);
                    serializedObjectString = dump_(serializedObject, param.asString, param.maxDepth);
                    if (logTextField_) logTextField_.appendText(dump_(serializedObject, true, param.maxDepth) + "\n");
                    if (outputTextField_) outputTextField_.appendText(dump_(serializedObject, true, param.maxDepth) + "\n");
                } else {
                    if (type) logString = '[' + type + '] ' + logString;
                    if (prefix) logString = '[' + prefix + '] ' + logString;
                    trace(logString);
                    if (outputTextField_) outputTextField_.appendText(logString + "\n");
    
    //              if (logTextField_) {
    //                  var i1:int = logTextField_.text.length - 1;
    //                  logTextField_.appendText(logString + "\n");
    //                  var i2:int = logTextField_.text.length - 1;
    //                  var logColor:uint = 0x000000;
    //                  if (type == "Info") logColor = 0xffffff;
    //                  if (type == "Warning") logColor = 0xECEC00;
    //                  if (type == "Error") logColor = 0xFF3535;
    //                  var tf:TextFormat = logTextField_.getTextFormat(i1, i2);
    //                  tf.color = logColor;
    //                  logTextField_.setTextFormat(tf, i1, i2);
    //              }
                }   
    
                if (logWindow_) logWindow_.parent.addChild(logWindow_);
                if (outputTextField_) outputTextField_.scrollV = outputTextField_.maxScrollV;
    
                if (ExternalInterface.available) {
                    try {
                        var c:String = "console.info";
                        var v:* = s;
                        if (prefix) v = '[' + prefix + '] ' + v;
                        if (type == "Warning") {
                            c = "console.warn";
                        } else if (type == "Error") {
                            c = "console.error";    
                        } else if (type == "Dump") {
                            if (param.asString) {
                                c = "console.info";
                                v = serializedObjectString ? serializedObjectString : s;
                            } else {
                                c = "console.dir";  
                                var h:String = "Dump";
                                if (prefix) h = prefix + "_" + h;
                                v = {};
                                v[h] = (serializedObject ? serializedObject : s);
                            }
                        }
                        ExternalInterface.call(c, v);                   
                    } catch(e:*) {
                        // ignore   
                    }
                }
            }   
    
    
            static public function info(s:*):void {
                log(s, 'Info');
            }
    
    
            static public function warning(s:*):void {
                log(s, 'Warning');
            }
    
    
            static public function error(s:*):void {
                log(s, 'Error');
            }
    
    
            static public function dump(s:*, asString:Boolean = false, maxDepth:int = -1):void {
                log(s, "Dump", { asString:asString, maxDepth:maxDepth });   
            }
    
    
            static public function get prefix():String {
                return prefix_; 
            }
    
    
            static public function set prefix(v:String):void {
                var validCharacters:String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
                var output:String = "";
                for (var i:int = 0; i < v.length; i++) {
                    var c:String = v.charAt(i);
                    if (validCharacters.indexOf(c) < 0) continue;
                    output += c;    
                }
                if (output.length == 0) output = "a";
    
                prefix_ = output;
            }
    
    
            static public function showLogWindow(parent:*):void {
                if (!logWindow_) {
                    logWindow_ = new Sprite();
    
                    logTextField_ = new TextField();
                    var tf:TextFormat = new TextFormat();
                    tf.font = "Arial";
                    tf.size = 10;
                    logTextField_.defaultTextFormat = tf;
                    logTextField_.multiline = true;
                    logTextField_.wordWrap = true;
                    logTextField_.border = true;
                    logTextField_.borderColor = 0xffffff;
    
                    closeLogWindowButton_= new TextField();
                    closeLogWindowButton_.text = "[Minimize]";
                    closeLogWindowButton_.autoSize = "left";
                    closeLogWindowButton_.selectable = false;
                    var tf:TextFormat = new TextFormat();
                    tf.font = "Arial";
                    tf.size = 10;
                    tf.color = 0xffffff;
                    closeLogWindowButton_.setTextFormat(tf);
                    closeLogWindowButton_.defaultTextFormat = tf;
                    closeLogWindowButton_.addEventListener("click", closeLogWindowButton_click);
    
                    logWindow_.addChild(logTextField_);
                    logWindow_.addChild(closeLogWindowButton_);
    
                    logWindowMaximized_ = true;
                }
    
                logWindowHeight_ = 240;
    
                updateLogWindowLayout(320, logWindowHeight_);
    
                parent.addChild(logWindow_);
    
                logWindow_.addEventListener("enterFrame", logWindow_enterFrame);
            }
    
    
            static public function hideLogWindow():void {
                if (!logWindow_) return;
                if (logWindow_.parent) logWindow_.parent.removeChild(logWindow_);
                logWindow_.removeEventListener("enterFrame", logWindow_enterFrame);
            }
    
    
            static public function minimizeLogWindow():void {
                if (!logWindowMaximized_) return;
                closeLogWindowButton_click(null);
            }
    
    
            static public function logWindow_enterFrame(event:*):void {
                if (logWindow_.parent) logWindow_.parent.addChild(logWindow_);
            }
    
    
            static private function updateLogWindowLayout(width:Number, height:Number):void {
                var m:Number = 8;
                closeLogWindowButton_.x = m;
                logTextField_.x = m;
                logTextField_.y = closeLogWindowButton_.height;
                logTextField_.width = width - 2 * m;
                logTextField_.height = Math.max(height - logTextField_.y - m, 0);
    
                logWindow_.graphics.clear();
                logWindow_.graphics.lineStyle(1, 0xffffff);
                logWindow_.graphics.beginFill(0x000000);
                logWindow_.graphics.drawRect(0,0,width,height);
                logWindow_.graphics.endFill();
            }
    
    
            static private function closeLogWindowButton_click(event:*):void {
                var doShow:Boolean = !logWindowMaximized_;
                var h:Number = doShow ? logWindowHeight_ : 10;
    
                logWindowMaximized_ = doShow;
    
                updateLogWindowLayout(doShow ? 320 : 10, h);
    
                closeLogWindowButton_.text = doShow ? '[Minimize]' : '  ';
                if (!doShow) {
                    closeLogWindowButton_.x = 0;
                    closeLogWindowButton_.y = 0;    
                }
    
                logTextField_.visible = doShow;
            }
    
    
    
    
    
    
            static private function serializeObject_(object:*, maxDepth:int = 8):* {
    
                var objectReferences:Dictionary = new Dictionary();
                var objectReferenceIndex:int = 0;
                var depth:int = 0;
                var inputObjectReferenceCount:int = 0;
    
                function serialize(o:*):* { 
    
                    if (o === object) inputObjectReferenceCount++;
    
                    depth++;
                    var objectIndex:int;
                    var output:*;
    
                    if (maxDepth >= 0 && depth > maxDepth) {
    
                        output = '<Max depth>';
    
                    } else {
    
                        var i:int;
    
                        if (objectReferences[o]) {
                            output = '<#' + objectReferences[o] + '>';
                        } else if (o === object && inputObjectReferenceCount > 1) {
                            output = '<#0>';
                        } else if (o === null || o === undefined || o is String || typeof(o) == "number" || o === true || o === false) {
                            output = o;
                        } else if (o is Array) {
    
                            output = [];
                            objectIndex = objectReferenceIndex++;
                            objectReferences[o] = objectIndex;
    
                            for (i = 0; i < o.length; i++) {
                                output.push(serialize(o[i]));
                            }
    
                        } else if (o is Object) {
    
                            output = {};
    
                            objectIndex = objectReferenceIndex++;
                            objectReferences[o] = objectIndex;
    
                            var xml:XML = describeType(o);
                            var typeName:String = xml.@name.toString();
                            var twoDots:int = typeName.indexOf("::");
                            if (twoDots >= 0) typeName = typeName.substr(twoDots + 2, typeName.length);
                            var isDynamic:Boolean = xml.@isDynamic.toString() == "true";
    
                            var v:*;
    
                            if (!isDynamic) {
                                var propertyNames:XMLList = xml..accessor.@name;
                                var properyName:String;
    
                                for (i = 0; i < propertyNames.length(); i++) {
                                    properyName = propertyNames[i].toString();
                                    try {
                                        v = o[properyName];
                                    } catch(e:*) {
                                        continue;
                                    }
                                    output[properyName] = serialize(v);
                                }
    
                                propertyNames = xml..variable.@name;
    
                                for (i = 0; i < propertyNames.length(); i++) {
                                    properyName = propertyNames[i].toString();
                                    try {
                                        v = o[properyName];
                                    } catch(e:*) {
                                        continue;
                                    }
                                    output[properyName] = serialize(v);
                                }
    
                            } else {
                                for (var n:String in o) {
                                    v = o[n];
                                    output[n] = serialize(v);
                                }
                            }
    
                        } else {
                            output = o;   
                        }
    
                    }
    
                    depth--;
                    return output;
                }    
    
                var finalOutput:* = serialize(object);
                return finalOutput;
            }
    
    
    
    
    
            static private function dump_(object:*, asString:Boolean = false, maxDepth:int = 8):* {
    
                var objectReferences:Dictionary = new Dictionary();
                var objectReferenceIndex:int = 0;
                var depth:int = 0;
    
                var inputObjectReferenceCount:int = 0;
    
                function objectToString(o:*, indent:Number = 1):String {    
    
                    if (o === object) inputObjectReferenceCount++;
    
                    depth++;
                    var objectIndex:int;
    
                    if (maxDepth >= 0 && depth > maxDepth) {
    
                        output = '<Max depth>';
    
                    } else {
    
                        var spaces:String = '';
                        var i:Number;
                        for (i = 0; i < indent; i++) spaces += '    ';
    
                        var output:String = '';
    
                        if (objectReferences[o]) {
                            output = '<#' + objectReferences[o] + '>';
                        } else if (o === object && inputObjectReferenceCount > 1) {
                            output = '<#0>';
                        } else if (o === null) {
                            output = "null";
                        } else if (o === undefined) {
                            output = "undefined";
                        } else if (o is String) {
                            output = '"' + o + '"';
                        } else if (typeof(o) == "number") {
                            output = o.toString();
                        } else if (o === true) {
                            output = "true";
                        } else if (o === false) {
                            output = "false";
                        } else if (o is Array) {
    
                            objectIndex = objectReferenceIndex++;
                            objectReferences[o] = objectIndex;
    
                            output += '(Array #' + objectIndex + ')';
    
                            if (o.length > 0) {
                                output += '\n';
                            } else {
                                output += '[]';   
                            }
                            indent++;
                            for (i = 0; i < o.length; i++) {
                                if (i > 0) output += '\n';
                                output += spaces + '[' + i + '] ' + objectToString(o[i], indent);
                            }
    
                        } else if (o is Object) {
    
                            var v:*;
                            objectIndex = objectReferenceIndex++;
                            objectReferences[o] = objectIndex;
                            indent++;
                            var propCount:int = 0;
                            output += '(' + 'Object' + ' #' + objectIndex + ')';
    
                            for (var n:String in o) {
                                v = o[n];
                                output += '\n';
                                output += spaces + n + ': ' + objectToString(v, indent);
                                propCount++;
                            }
    
                            if (propCount == 0) output += '{}';
    
                        } else {
                            output += o;   
                        }
    
                    }
    
                    depth--;
                    return output;
                }    
    
                var s:String = objectToString(object);
    
                if (asString) return s;
    
                trace(s);       
            }
    
    
        }
    
    }