/*
* hexagon framework - Multi-Purpose ActionScript 3 Framework.
* Copyright (C) 2007 Hexagon Star Softworks
* __ __
* __/ \__/ \__ __
* / \__/HEXAGON \__/ \
* \__/ \__/ FRAMEWORK_/
* \__/ \__/
*
* ``The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*/
package com.hexagonstar.util.debug
{
import flash.display.Stage;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.events.StatusEvent;
import flash.net.LocalConnection;
import flash.net.SharedObject;
import flash.net.SharedObjectFlushStatus;
import flash.system.Security;
import flash.system.SecurityPanel;
import flash.system.System;
import flash.utils.ByteArray;
/**
* Alcon Debug class (AS 3.0 version)
* Sends trace actions to the Alcon output panel through a local connection.
*
* @version 2.0.1 (2007.03.26)
*/
public final class Debug
{
// Constants //////////////////////////////////////////////////////////////////
public static const LEVEL_DEBUG:uint = 0;
public static const LEVEL_INFO:uint = 1;
public static const LEVEL_WARN:uint = 2;
public static const LEVEL_ERROR:uint = 3;
public static const LEVEL_FATAL:uint = 4;
// Properties /////////////////////////////////////////////////////////////////
private static var _fpsPollInterval:uint = 1000;
private static var _filterLevel:uint = 0;
private static var _isConnected:Boolean = false;
private static var _isPollingFPS:Boolean = false;
private static var _isDisabled:Boolean = false;
private static var _isLargeData:Boolean = false;
private static var _connection:LocalConnection;
private static var _stopWatch:StopWatch;
private static var _fpsMeter:FPSMeter;
private static var _stage:Stage;
// Constructor ////////////////////////////////////////////////////////////////
/**
* Internal Constructor
*/
function Debug()
{
}
// Public Methods /////////////////////////////////////////////////////////////
/**
* The trace method accepts three arguments, the first contains the data which
* is going to be traced, the second if of type Boolean is used to indicate
* recursive object tracing mode, if of type int desribes the filtering level
* for the output.
*
* @param arg0 The object to be traced (defaults to undefined).
* @param arg1 True if recursive object tracing, optional (defaults to null).
* @param arg2 Output level, optional, defaults to 1.
*/
public static function trace(arg0:* = undefined, arg1:* = null, arg2:int = -1):void
{
var data:* = arg0;
var recursive:Boolean = false;
var level:int = 1;
// Check if argument 1 is a boolean or a number:
if (typeof(arg1) == "boolean")
{
recursive = arg1;
}
else if (typeof(arg1) == "number")
{
level = arg1;
}
if (arg2 > -1)
{
level = arg2;
}
// Only show messages equal or higher than current filter level:
if (level >= _filterLevel && level < 7)
{
// Send the data to the output console:
send("onData", data, level, ((recursive) ? 1 : 0));
}
}
/**
* Can be used to inspect the specified object. This method sends the object
* to the Alcon output panel where it is displayed in the Inspect tab.
*
* @param object The object to be inspected.
* @param depth The depth with that to inspect the object. If this argument
* is -1 or omitted, the default from Alcon's config file will be used.
*/
public static function inspect(object:Object = null, depth:int = -1):void
{
send("onInspect", object, 1, depth);
}
/**
* Outputs a hexadecimal dump of the specified object.
*
* @param object The object of which to output a hex dump.
*/
public static function hexDump(object:*):void
{
send("onHexDump", object, 0, 0);
}
/**
* Forces an immediate Garbage Collector mark/sweep. Use with caution!
* This method is not officially supported by the Flash Player!
*/
public static function forceGC():void
{
try
{
new LocalConnection().connect("forceGC");
new LocalConnection().connect("forceGC");
}
catch (e:Error)
{
}
}
/**
* Sends a clear buffer signal to the output console. The Trace tab will be
* cleared after this signal is received.
*/
public static function clear():void
{
Debug.trace("[%CLR%]", 5);
}
/**
* Sends a delimiter signal to the output console.
*/
public static function delimiter():void
{
Debug.trace("[%DLT%]", 5);
}
/**
* Sends a pause signal to the output console.
*/
public static function pause():void
{
Debug.trace("[%PSE%]", 5);
}
/**
* Sends a time/date signal to the output console.
*/
public static function time():void
{
Debug.trace("[%TME%]", 5);
}
/**
* Sets the current logging filter level.
*
* @param level A value for the filter level to be set. If no argument
* is specified, 0 is used as default.
*/
public static function setFilterLevel(level:uint = 0):void
{
if (level >= 0 && level < 5) _filterLevel = level;
}
/**
* Returns the currently used logging filter level.
*
* @return The current filter level.
*/
public static function getFilterLevel():int
{
return _filterLevel;
}
/**
* Disables the output coming from the Debug class. This can be used
* to quickly suppress all debug output without needing to remove
* function calls to the Debug class and it's imports.
*/
public static function disable():void
{
_isDisabled = true;
}
// FPS Polling Methods ////////////////////////////////////////////////////////
/**
* When called starts measuring the current host applications frames per
* second and sends the FPS value and the current amount of memory used by
* the host applications Flash Player to the Alcon output console.
*
* @param stage The Stage of the current host application.
*/
public static function fpsStart(stage:Stage):void
{
if (!_isDisabled && _fpsMeter == null)
{
_isPollingFPS = true;
_stage = stage;
_fpsMeter = new FPSMeter(stage);
_fpsMeter.addEventListener(FPSMeter.FPS_UPDATE, onFPSUpdate);
_fpsMeter.start();
}
}
/**
* Stops the FPS polling.
*/
public static function fpsStop():void
{
if (_fpsMeter != null)
{
_isPollingFPS = false;
_fpsMeter.stop();
_fpsMeter.removeEventListener(FPSMeter.FPS_UPDATE, onFPSUpdate);
_fpsMeter = null;
}
}
// Timer Methods //////////////////////////////////////////////////////////////
/**
* Starts the Stowatch to measure a time amount.
*/
public static function timerStart(title:String = ""):void
{
if (!_isDisabled)
{
if (_stopWatch == null) _stopWatch = new StopWatch();
_stopWatch.start(title);
}
}
/**
* Stops the Stowatch.
*/
public static function timerStop():void
{
if (_stopWatch != null) _stopWatch.stop();
}
/**
* Resets the Stopwatch.
*/
public static function timerReset():void
{
if (_stopWatch != null) _stopWatch.reset();
}
/**
* Sends the measured time in milliseconds to the output console.
*/
public static function timerMilliSeconds():void
{
if (_stopWatch != null) Debug.trace(_stopWatch.getTimeInMilliSeconds() + "ms");
}
/**
* Sends the measured time in seconds to the output console.
*/
public static function timerSeconds():void
{
if (_stopWatch != null) Debug.trace(_stopWatch.getTimeInSeconds() + "s");
}
/**
* Sends the measured time to the output console. This automatically
* formats the values to seconds and milliseconds.
*/
public static function timerToString():void
{
if (_stopWatch != null) Debug.trace(_stopWatch.toString());
}
/**
* Stops the Stopwatch and immediately Sends the measured time to the
* output console in the same manner like timerToString().
*
* @param reset If true resets the Timer after the result has been output.
*/
public static function timerStopToString(reset:Boolean = false):void
{
if (_stopWatch != null)
{
_stopWatch.stop();
Debug.trace(_stopWatch.toString());
if (reset) _stopWatch.reset();
}
}
// Private Methods ////////////////////////////////////////////////////////////
/**
* Sends the specified data.
*
* @private
*/
private static function send(method:String, data:*, level:int = 1, rec:uint = 0):void
{
// Only send if Debug is not disabled:
if (!_isDisabled)
{
// Establish connection if not already done:
if (!_isConnected)
{
_isConnected = true;
_connection = new LocalConnection();
_connection.addEventListener(StatusEvent.STATUS, onStatus);
}
// Get the size of the data:
var size:uint = 0;
if (typeof(data) == "string")
{
size = String(data).length;
}
else if (typeof(data) == "object")
{
var byteArray:ByteArray = new ByteArray();
byteArray.writeObject(data);
size = byteArray.length;
byteArray = null;
}
// If the data size exceeds 39Kb, use a LSO instead:
if (size > 39000)
{
storeDataLSO(method, data);
method = "onLargeData";
data = null;
}
_connection.send("_alcon_lc", method, data, level, rec, "");
}
}
/**
* Stores data larger than 40Kb to a Local Shared Object.
*
* @private
*/
private static function storeDataLSO(method:String, data:*):void
{
var sharedObject:SharedObject = SharedObject.getLocal("alcon", "/");
sharedObject.data.alconMethod = method;
sharedObject.data.alconData = data;
try
{
var flushResult:String = sharedObject.flush();
if (flushResult == SharedObjectFlushStatus.FLUSHED)
{
return;
}
}
catch (e:Error)
{
Security.showSettings(SecurityPanel.LOCAL_STORAGE);
}
}
/**
* Called on every fpsUpdate event.
*
* @private
*/
private static function onFPSUpdate(event:Event):void
{
send("onFPS", (_fpsMeter.getFPS() + "/" + _stage.frameRate + "|" + System.totalMemory));
}
/**
* onStatus method
*
* @private
*/
private static function onStatus(event:StatusEvent):void
{
}
}
}