The aim of this document is to gather informations, snippets, tips and links not provided by any official documentation, related to Flash Platform or others ECMAScript languages.
Flash renames bitmap fonts and adds the suffix: _{size}pt_st, where {size} is the bitamp size of the font.
Exemple:
Verdana_12pt_stArial_12pt_stIn FlashPlayer 9, to apply alpha, use filters, cacheAsBitmap or blend mode "layer"
textField.filters = [new BlurFilter(0,0,0)];//use emtpy filter to cache text
//or
textField.blendMode = BlendMode.LAYER;
//and finaly
textField.alpha = 0.5;
For other effect (rotation, scale, etc.) draw TextField in a BitmapData
In FlashPlayer 10, no more problems with alpha, but remain for transfrom effects like rotation, scale, etc.
In FlashPlayer 10 flash.text.engine natively support it
flash.external::ExternalInterface$/_callIn
6 to 9 month for all new version to reach ~90% of adoption
/**
*
* Copyright 2007
*
* Paulius Uza
* http://www.uza.lt
* http://www.uza.lt/blog/2007/08/solved-right-click-in-as3
*
* Dan Florio
* http://www.polygeek.com
*
* Project website:
* http://code.google.com/p/custom-context-menu/
*
* --
* RightClick for Flash Player.
* Version 0.6.2
*
*/
var RightClick = {
/**
* Constructor
*/
init: function () {
this.FlashObjectID = "customRightClick";
this.FlashContainerID = "flashcontent";
this.Cache = this.FlashObjectID;
if(window.addEventListener){
window.addEventListener("mousedown", this.onGeckoMouse(), true);
} else {
document.getElementById(this.FlashContainerID).onmouseup = function() { document.getElementById(RightClick.FlashContainerID).releaseCapture(); }
document.oncontextmenu = function(){ if(window.event.srcElement.id == RightClick.FlashObjectID) { return false; } else { RightClick.Cache = "nan"; }}
document.getElementById(this.FlashContainerID).onmousedown = RightClick.onIEMouse;
}
},
/**
* GECKO / WEBKIT event overkill
* @param {Object} eventObject
*/
killEvents: function(eventObject) {
if(eventObject) {
if (eventObject.stopPropagation) eventObject.stopPropagation();
if (eventObject.preventDefault) eventObject.preventDefault();
if (eventObject.preventCapture) eventObject.preventCapture();
if (eventObject.preventBubble) eventObject.preventBubble();
}
},
/**
* GECKO / WEBKIT call right click
* @param {Object} ev
*/
onGeckoMouse: function(ev) {
return function(ev) {
if (ev.button != 0) {
RightClick.killEvents(ev);
if(ev.target.id == RightClick.FlashObjectID && RightClick.Cache == RightClick.FlashObjectID) {
RightClick.call();
}
RightClick.Cache = ev.target.id;
}
}
},
/**
* IE call right click
* @param {Object} ev
*/
onIEMouse: function() {
if (event.button > 1) {
if(window.event.srcElement.id == RightClick.FlashObjectID && RightClick.Cache == RightClick.FlashObjectID) {
RightClick.call();
}
document.getElementById(RightClick.FlashContainerID).setCapture();
if(window.event.srcElement.id)
RightClick.Cache = window.event.srcElement.id;
}
},
/**
* Main call to Flash External Interface
*/
call: function() {
document.getElementById(this.FlashObjectID).rightClick();
}
}
ExternalInterface JavaScript evaluationExternalInterface evaluate given JavaScript string (anonymous functions): ExternalInterface.call("(function(param1, param2) {/* javascript code here */})", parameter1, parameter2);
Note: don’t use the dash character "-" or other special chars in the DOM id of your flash element. IE need id attribute for using ExtenralInterface, others need name attribute.
function __flash__arrayToXML(obj)
{
var s = "<array>";
for (var i=0; i<obj.length; i++)
s += "<property id=\"" + i + "\">" + __flash__toXML(obj[i]) + "</property>";
return s+"</array>";
}
function __flash__argumentsToXML(obj, index)
{
var s = "<arguments>";
for (var i=index; i<obj.length; i++)
s += __flash__toXML(obj[i]);
return s+"</arguments>";
}
function __flash__objectToXML(obj)
{
var s = "<object>";
for (var prop in obj)
s += "<property id=\"" + prop + "\">" + __flash__toXML(obj[prop]) + "</property>";
return s+"</object>";
}
function __flash__escapeXML(s)
{
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
}
function __flash__toXML(value)
{
var type = typeof(value);
if (type == "string")
return "<string>" + __flash__escapeXML(value) + "</string>";
else if (type == "undefined")
return "<undefined/>";
else if (type == "number")
return "<number>" + value + "</number>";
else if (value == null)
return "<null/>";
else if (type == "boolean")
return value ? "<true/>" : "<false/>";
else if (value instanceof Date)
return "<date>" + value.getTime() + "</date>";
else if (value instanceof Array)
return __flash__arrayToXML(value);
else if (type == "object")
return __flash__objectToXML(value);
else
return "<null/>"; //???
}
function __flash__addCallback(instance, name)
{
instance[name] = function()
{
return eval(instance.CallFunction("<invoke name=\""+name+"\" returntype=\"javascript\">" + __flash__argumentsToXML(arguments,0) + "</invoke>"));
}
}
function __flash__removeCallback(instance, name)
{
instance[name] = null;
}
FLfile.runCommandLine("command line here");
var frame = fl.getDocumentDOM().timelines[0].layers[0].frames[0];
var headerText = "[SWF(width=800, height=800, backgroundColor=0xffffff, frameRate=24)]\n"
+ "stage.align = StageAlign.TOP_LEFT;\n"
+ "stage.scaleMode = StageScaleMode.NO_SCALE;\n\n";
frame.actionScript = headerText + frame.actionScript;
[Transient] metadatapackage
{
[RemoteClass(alias="FooVO")]
public class FooVO
{
// public field
public var prop1:String;
// hidden field
[Transient]
public var prop2:Array;
}
}
Applied in all places using AMF encoding (RemoteObject, NetConnection, byteArray.readObject();)
See flash.net.registerClassAlias()
xml.setNotification(callback:Function);
function callback(currentTarget:Object, type:String, target:Object, value:Object, detail:Object):void;
Types:
attributeAddedattributeChangedattributeRemovednodeAddednodeChangednodeRemovednameSetnamespaceAddednamespaceRemovednamespaceSettextSetExemple:
<node name="Mike" age="34"><address><![CDATA[Fake address]]></address></node>
Get in items all XML nodes node:
xml.node.(items.push(new User(@name, uint(@age))));
The same but with address:
xml.node.(
items.push(item = new User(@name, uint(@age))),
item.address = address[0].toString()
);
Get all nodes with age greater than 30:
xml.node.(int(@age)>30).(
items.push(item = new User(@name, uint(@age))),
item.address = address[0].toString()
);
The same but with only one cycle
xml.node.(
// ?: condition
int(@age)>30 ? (
// if condition equals TRUE actions, separated by commas
item = new User(@name, uint(@age)),
items.push(item),
item.address = address[0].toString()
) : false // if condition equals FALSE actions
);
//http://www.morearty.com/blog/2009/04/01/aprilscript-actionscript-worst-practices/
package {
import flash.display.*
import flash.text.*
public class AprilFools extends Sprite {
エイプリルフール var Number = 4..toString()
use namespace エイプリルフール
function AprilFools()
{
get = set
set = get
with (createTextField())
text = new Date(Number).toDateString()
}
function get get() { return Number + <><{Number}
b={"/"+Number.split(/\//)[0]*502.25}/>..@b }
function set get(set) { Number = set+'/'+set/4 }
function get set() { return Number }
function set set(get) { Number = get }
// nothing fun here
function createTextField():TextField
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
var textField:TextField = new TextField();
textField.width = 1000;
addChild(textField);
return textField;
}
}
}
namespace エイプリルフール
i = -~i;//equal to i++
i = ~-i;//i--
Bugs : Talk:ASDoc:Creating ASDoc Comments - Adobe Labs
Don't use <code></code> in your @see text description.
The comment: /** @see "oops can't document this." */ will also cause the same exception
flash.display.DisplayObject.accessibilityProperties and flash.accessibility.*flash.utils.ByteArray.uncompress, flash.utils.ByteArray.deflate, FZip, ziplib)mxmlc -link-report=link-report.xml)cacheAsBitmap\f\r\n\t\v\0[\b]\s[\f\n\r\t\v\u00A0\u2028\u2029]).\S[^\f\n\r\t\v\u00A0\u2028\u2029]).\w[a-zA-Z0-9_]).\W[^a-zA-Z0-9_]).\d[0-9]).\D[^0-9]).\b\B[^\b]).\cX\cm matches control-M.\xhhhh.\uhhhhhhhh.DisplayObject into a BitmapDatavar clip:DisplayObject;
var bounds:Rectangle = clip.getBounds(clip);
var bitmap:BitmapData = new BitmapData(uint(bounds.width + 0.5), uint(bounds.height + 0.5), true, 0);
bitmap.draw(clip, new Matrix(1, 0, 0, 1, -bounds.x, -bounds.y));
DisplayObjectDraw it into a BitmapData (see above) with scale
var clip:DisplayObject;
var scale:Number = 0.5;
var bounds:Rectangle = clip.getBounds(clip);
var bitmap:BitmapData = new BitmapData(uint((bounds.width + 0.5) * scale), uint((bounds.height + 0.5) * scale), true, 0);
bitmap.draw(clip, new Matrix(scale, 0, 0, scale, -bounds.x, -bounds.y));
Then, set bitmap width & height to original sizes (bounds.width & bounds.height)
drawTriangleBitmapData capturevideo.attachNetStream(null);
var snapshot:BitmapData = new BitmapData(…);
snapshot.draw(video);
video.attachNetStream(stream);
public static function drawDonut(g:Graphics, radius1:Number, radius2:Number, startAngle:Number, endAngle:Number, x:Number = 0, y:Number = 0) : void
{
var segAngle:Number = Math.PI/4;
var angle:Number = startAngle;
var angleMid:Number, bx:Number, by:Number, cx:Number, cy:Number, i:Number;
var arc:Number = endAngle - angle;
if(arc == 0)
return;
while(arc < 0)
arc += Math.PI * 2;
var segs:Number = Math.ceil(arc / segAngle);
var rest:Number = arc % segAngle;
var theta:Number = segAngle / 2;
var cosTheta:Number = Math.cos(theta);
var ax1:Number = Math.cos(angle) * radius1;
var ay1:Number = Math.sin(angle) * radius1;
var ax2:Number = Math.cos(angle) * radius2;
var ay2:Number = Math.sin(angle) * radius2;
g.moveTo(ax1 + x, ay1 + y);
g.lineTo(ax2 + x, ay2 + y);
for(i = 0 ; i < segs - 1 ; i++)
{
angle += segAngle;
angleMid = angle - theta;
bx = x + Math.cos(angle) * radius2;
by = y + Math.sin(angle) * radius2;
cx = x + Math.cos(angleMid) * (radius2 / cosTheta);
cy = y + Math.sin(angleMid) * (radius2 / cosTheta);
g.curveTo(cx, cy, bx, by);
}
angle += rest;
angleMid = angle - rest / 2;
bx = x + Math.cos(angle) * radius2;
by = y + Math.sin(angle) * radius2;
cx = x + Math.cos(angleMid) * (radius2 / Math.cos(rest / 2));
cy = y + Math.sin(angleMid) * (radius2 / Math.cos(rest / 2));
g.curveTo(cx, cy, bx, by);
ax1 = Math.cos(endAngle) * radius1;
ay1 = Math.sin(endAngle) * radius1;
g.lineTo(ax1 + x, ay1 + y);
angle -= rest;
bx = x + Math.cos(angle) * radius1;
by = y + Math.sin(angle) * radius1;
cx = x + Math.cos(angleMid) * (radius1 / Math.cos(rest / 2));
cy = y + Math.sin(angleMid) * (radius1 / Math.cos(rest / 2));
g.curveTo(cx, cy, bx, by);
for(i = segs-2 ; i > -1 ; i--)
{
angle -= theta * 2;
angleMid = angle + theta;
bx = x + Math.cos(angle) * radius1;
by = y + Math.sin(angle) * radius1;
cx = x + Math.cos(angleMid) * (radius1 / cosTheta);
cy = y + Math.sin(angleMid) * (radius1 / cosTheta);
g.curveTo(cx, cy, bx, by);
}
}
URLLoader/**
* Original:
* http://www.jooce.com/blog/?p=143
* Uploads a file using a given URLLoader object.
*
* @param loader The URLLoader object to use
* @param url The location of the script recieving the upload
* @param file The file to upload
* @param fileName The name of the file
* @param contentType The content-type of the file
*/
var loader:URLLoader = new URLLoader();
var file:ByteArray = new ByteArray();
file.writeUTFBytes("Fake file content text.");
var request:URLRequest = new URLRequest("my/path/upload.php");
var fileName:String = "myfile.txt";
var contentType:String = "text/plain";//"application/octet-stream"
var i:int;
var boundary:String = "--";
var postData:ByteArray = new ByteArray;
var bytes:String;
for(i = 0; i < 0x10; i++)
boundary += String.fromCharCode(int(97 + Math.random() * 25));
loader.dataFormat = URLLoaderDataFormat.BINARY;
request.url = url;
request.contentType = "multipart/form-data; boundary=" + boundary;
request.method = URLRequestMethod.POST;
postData.endian = Endian.BIG_ENDIAN;
// -- + boundary
postData.writeShort(0x2d2d);
for (i = 0; i < boundary.length; i++)
postData.writeByte(boundary.charCodeAt(i));
// line break
postData.writeShort(0x0d0a);
// content disposition
bytes = "Content-Disposition: form-data; name=\"Filename\"";
for (i = 0; i < bytes.length; i++)
postData.writeByte(bytes.charCodeAt(i));
// 2 line breaks
postData.writeInt(0x0d0a0d0a);
// file name
postData.writeUTFBytes(fileName);
// line break
postData.writeShort(0x0d0a);
// -- + boundary
postData.writeShort(0x2d2d);
for (i = 0; i < boundary.length; i++)
postData.writeByte(boundary.charCodeAt(i));
// line break
postData.writeShort(0x0d0a);
// content disposition
bytes = "Content-Disposition: form-data; name=\"Filedata\"; filename=\"";
for (i = 0; i < bytes.length; i++)
postData.writeByte(bytes.charCodeAt(i));
// file name
postData.writeUTFBytes(fileName);
// missing "
postData.writeByte(0x22);
// line break
postData.writeShort(0x0d0a);
// content type
bytes = "Content-Type: " + contentType;
for (i = 0; i < bytes.length; i++)
postData.writeByte(bytes.charCodeAt(i));
// 2 line breaks
postData.writeInt(0x0d0a0d0a);
// file data
postData.writeBytes(file, 0, file.length);
// line break
postData.writeShort(0x0d0a);
// -- + boundary
postData.writeShort(0x2d2d);
for (i = 0; i < boundary.length; i++)
postData.writeByte(boundary.charCodeAt(i));
// line break
postData.writeShort(0x0d0a);
// upload field
bytes = "Content-Disposition: form-data; name=\"Upload\"";
for (i = 0; i < bytes.length; i++)
postData.writeByte(bytes.charCodeAt(i));
// 2 line breaks
postData.writeInt(0x0d0a0d0a);
// submit
bytes = "Submit Query";
for (i = 0; i < bytes.length; i++)
postData.writeByte(bytes.charCodeAt(i));
// line break
postData.writeShort(0x0d0a);
// -- + boundary + --
postData.writeShort(0x2d2d);
for (i = 0; i < boundary.length; i++)
postData.writeByte(boundary.charCodeAt(i));
postData.writeShort(0x2d2d);
request.data = postData;
request.requestHeaders.push(new URLRequestHeader("Cache-Control", "no-cache"));
loader.load(request);
var dic:Dictionary = new Dictionary(false);
var data:XML = <data><node/></data>;
dic[data] = true;
var node:XML = data.node[0];
trace(dic[data])
//output: true
trace(dic[node.parent()])//must be true (see after)
//output: undefined
for(var key:* in dic)
trace(key == node.parent(), key === node.parent())//output: true true
http://www.zeuslabs.us/2007/01/30/flash-floating-point-number-errors/
/**
* Corrects errors caused by floating point math.
*/
public function correctFloatingPointError(number:Number, precision:int = 5):Number
{
//default returns (10000 * number) / 10000
//should correct very small floating point errors
var correction:Number = Math.pow(10, precision);
return Math.round(correction * number) / correction;
}
/**
* Tests if two numbers are almost equal.
*/
public function fuzzyEquals(number1:Number, number2:Number, precision:int = 5):Boolean
{
var difference:Number = number1 - number2;
var range:Number = Math.pow(10, - precision);
//default check:
//0.00001 - 0.00001
return difference < range && difference > - range;
}
/*
[code]
//*/
//*
[code]
//*/
Only add / char to comment
//*
[code 1]
/*/
[code 2]
//*/
/*
[code 1]
/*/
[code 2]
//*/
Works also on related comment
y = x << 1;//equals (~300% faster) to: y = x * 2;
y = x << 6;//y = x * 64
y = x >> 1;//equals (~350% faster) to: y = x / 2;
y = x >> 6;//y = x / 64
y = x >> 0;//equals to: y = int(x); or y = Math.floor(x);
var _24bitsColor:uint = 0xff00cc;
var r:uint = _24bitsColor >> 16;
var g:uint = _24bitsColor >> 8 & 0xff;
var b:uint = _24bitsColor & 0xff;
Or 32 bit color (argb)
var _32bitsColor:uint = 0xddff00cc;
var a:uint = _32bitsColor >> 24 & 0xff;
var r:uint = _32bitsColor >> 16 & 0xff;
var g:uint = _32bitsColor >> 8 & 0xff;
var b:uint = _32bitsColor & 0xff;
//Or alpha and 24 bits color:
var a:uint = _32bitsColor >> 24 & 0xff;
var _24bitsColor:uint = _32bitsColor & 0xffffff;
var r:uint = 0xff;
var g:uint = 0x00;
var b:uint = 0xcc;
var _24bitColor:uint = r << 16 | g << 8 | b;
Or 32 bit color (argb)
var a:uint = 0xdd;
var r:uint = 0xff;
var g:uint = 0x00;
var b:uint = 0xcc;
var _32bitColor:uint = a << 24 | r << 16 | g << 8 | b;
x ^= y;
y ^= x;
x ^= y;
/*
equals (~20% faster) to:
var z:int = x;
x = y;
y = z;
*/
x = ~x + 1;//or
x = (x ^ -1) + 1;//equals (~300% faster) to x = -x;
z = x & (y - 1);//equals to z = x % y;
(x % y) == 0;//equals (~600% faster) to: (x & (y - 1)) == 0
y = x < 0 ? -x : x;//equals (~2500% faster) to: y = Math.abs(x); or
y = (x ^ (x >> 31)) - (x >> 31);//equals (~20% faster) to Math.abs()
z = x ^ y > 0;//equals (~35% faster) to: z = x * y > 0;
//Set differents flags
var flags:uint = FLAG_1 | FLAG_2;
//Add one flag
flags |= FLAG_3;
//Remove flag
flags &= ~FLAG_4;
//Get flag
var flag:Boolean = flags & FLAG_2 > 0;
Where flag are unsigned integer with value power of 2: (0, 0x0), (1, 0x1), (2, 0x2, 1 << 1), (4, 0x4, 1 << 2), …
y = !(x & (x - 1)) && x;
Where x is integer tested and y is "if is power of 2".
var myWord:String = "mychar";
if(~myWord.indexOf("d"))
trace("found")
else
trace("not found")
y = (x >>> offset) & (0xffffffff >>> 32 - numBits);//or
y = (x >>> offset) & (Math.pow(2, numBits) - 1);
Where x is an unsigned interger and numBits is value of bits need to extract.
With (final contructor) != is keyword
public static function typeEquals(object:*, constructor:Class):Boolean
{
return o == null ? false : Object(object).constructor == constructor;
}
ArrayAnd support Array's arguments
public class SubArray extends Array
{
function SubArray():void
{
super.constructor.apply(this, arguments);
}
}
SuperClass.prototype.isPrototypeOf(SubClass.prototype);
if (0)
super();
Angle between 0° and 360°
angle = (angle % 360 + 360) % 360;
Angle between -180° and 180°
angle = (angle % 360 + 540) % 360 - 180;
Infinit index
var values:Array = ["a", "b", "c"];
var index:int = -5;
var length:uint = values.length;
var realIndex:uint = (index % length + length) % length;// = 0, 1 or 2
values[realIndex];//= "b"
Fit all
var ratioSource:Number = displayObject.width / displayObject.height;
var ratioTarget:Number = WIDTH_TARGET / HEIGHT_TARGET;
var newWidth:Number = Math.min(ratioSource, ratioTarget) * HEIGHT_TARGET;
var newHeight:Number = WIDTH_TARGET / Math.max(ratioSource, ratioTarget);
Fit all (with original max size)
var widthTarget:Number = Math.min(WIDTH_TARGET, displayObject.width);
var heightTarget:Number = Math.min(HEIGHT_TARGET, displayObject.height);
var ratioSource:Number = displayObject.width / displayObject.height;
var ratioTarget:Number = widthTarget / heightTarget;
var newWidth:Number = Math.min(ratioSource, ratioTarget) * heightTarget;
var newHeight:Number = widthTarget / Math.max(ratioSource, ratioTarget);
Crop to fit
var ratioSource:Number = displayObject.width / displayObject.height;
var ratioTarget:Number = WIDTH_TARGET / HEIGHT_TARGET;
var newWidth:Number = Math.max(ratioSource, ratioTarget) * HEIGHT_TARGET;
var newHeight:Number = WIDTH_TARGET / Math.min(ratioSource, ratioTarget);
var duration:Number = this.sound.length;
if (this.sound.bytesTotal != this.sound.bytesLoaded && duration > 0)
duration = (this.sound.bytesTotal / (this.sound.bytesLoaded / duration));
Assuming continuous bitrate (average), tested regularly.
if (duration > 0)
{
var bufferingDuration:Number = getTimer() - startTimer;
var totalLoadTime:Number = bytesLoaded == 0 ? Number.POSITIVE_INFINITY : bytesTotal / bytesLoaded * bufferingDuration;
var duration:Number = duration * 1000;//s -> ms
trace("(" + bytesLoaded + "/" + bytesTotal + ")" + bufferingDuration + " : " + totalLoadTime.toFixed(2))
if (totalLoadTime < duration || bufferingDuration + duration > totalLoadTime)
//tracehere video can be play with
}
Where startTimer is value of getTimer() defined at begin of video loading and duration is length of video.
try
{
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');//The GC will perform a full mark/sweep on the second call.
} catch (error:*) {}
LocalConnection limitsLocalConnection.send() limited to 40960 bytes. For one ByteArray is limited to 40864 (+ AMF data for one ByteArray: 96 bytes ?)
Error.throwError(RangeError, 1005 /*kArrayIndexNotIntegerError*/, -3);//throw Error #1005: Array index is not an integer (-3) Error.throwError(type:Class, errorID:uint, …rest);
namespace flash_events = "flash.events";
trace(flash_events::MouseEvent); //output: [class MouseEvent]
Event.OPENProgressEvent.PROGRESS * nEvent.INITHTTPStatusEvent.HTTP_STATUSEvent.COMPLETEhttps://www.macromedia.com/bin/flashdownload.cgi?product=fpupdatept&signed=true&A=t&SA=t&SV=t&EV=t&MP3=t&AE=t&VE=t&ACC=f&PR=t&SP=t&SB=f&DEB=t&V=WIN%209%2C0%2C115%2C0&M=Adobe%20Windows&R=1920x1200&DP=72&COL=color&AR=1.0&OS=Windows%20XP&L=fr&IME=f&PT=External&AVD=f&LFD=f&WD=f&TLS=t&what=descr…
Product("digitaleditions2x0")
//AS2
var p = new System.Product("notepad");
p.download();
trace(p.IsInstalled());
trace(p.Launch());
And you copy "notepad.exe" to
// ApplicationData\Macromedia\FlashPlayer\www.macromedia.com\bin\notepad\
//AS3
var p:ProductManager = new adobe.utils.ProductManager()
p.launch();
p.download();
p.installed;
p.installedVersion;
p.running;
//AS3 launch AIR app
myLauncher:ProductManager = new ProductManager("airappinstaller");
var myArguments:Array = ["-launch", appID, publisherID, theOtherAppArguments];
myLauncher.launch(myArguments.join(" "));
fpupdateaxdigitaleditions2x0airappinstallerfpupdateplimport flash.sampler.getMemberNames;
...
var members:Object = getMemberNames(myObject);
for each (var name:QName in members)
if (name.localName == "memberName")
trace(myObject[name]);
loader.contentLoaderInfo.applicationDomain.getDefinition("FullQualifiedClassName") as Class
//Before = After - 5.5 months
var monthRatio:Number = 5.5;
var today:Date = new Date();
//trace("today: " + today.toDateString())
var after:Date = new Date(today.fullYear, today.month, today.date);
trace("after: " + after.toDateString());
var before:Date = new Date(today.fullYear, (today.month - uint(monthRatio)), 32);
trace((32 - before.date) + " jours");
before = new Date(before.fullYear, (today.month - uint(monthRatio)), today.date - Math.round(monthRatio % 1 * (32 - before.date)))
trace("before (after - " + monthRatio + " months): " + before.toDateString())
Not work on DisplayObjects
//http://niko.informatif.org/blog/2007_07_20_clone_an_object_in_as3
package nc.utils
{
import flash.utils.ByteArray;
import flash.net.registerClassAlias;
import flash.utils.getQualifiedClassName;
import flash.net.getClassByAlias;
import flash.utils.describeType;
import flash.utils.getDefinitionByName;
public class ObjectUtils
{
/**
* Clone an Object
*
* @param object The Object to clone (Object is not a part of the displayList
* and object don't need arguments in constructor)
*
* @param type The Class of the Object to clone.
*
* @return a clone of Object
*/
public static function clone(object:*):*
{
var alias:String = getQualifiedClassName(object).split('::').join('.');
var type:Class = getDefinitionByName(alias) as Class;
traverse(object);
var r:ByteArray = new ByteArray();
r.writeObject(object);
r.position = 0;
var clone:*;
try
{
clone = r.readObject();
return clone as type;
}
catch(error:TypeError)
{
//trace(error);
}
return null;
}
private static function traverse(object:*):void
{
var alias : String = getQualifiedClassName(object).split('::').join('.');
var type : Class = getDefinitionByName(alias) as Class;
try
{
getClassByAlias(alias);
}
catch(error:ReferenceError)
{
registerClassAlias(alias, type);
}
var x:XML = describeType(object),
childrens:XMLList = x.children(),
l:int = childrens.length(),
i:int = -1,
xClass:XML;
while (++i " + alias + " as " + type);
registerClassAlias(alias, type);
}
}
}
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd">;
<allow-access-from domain="*" to-ports="*" secure="false" />
<site-control permitted-cross-domain-policies="master-only" />
</cross-domain-policy>
Deliver policy file with command line PHP
#!/usr/local/bin/php
<?php
/**
* Flash Policy Service v0.9.c
*
* This script listens for <policy-file-request/> on port 843 and serves up
* an xml crossdomain policy file. This sort of service is necessary if any
* flash content is going to connect to sockets on the running host.
*
* I have made every effort to package everything you need into a single
* file here, even though it could easily have been split into 3 or more
* scripts.
*
* Requirements:
* - PHP 5 with sockets, pcntl, and posix extensions
* - Root access (to bind to a <1024 port)
*
* Use:
* Simply execute the script from the command line as root:
* # ./FlashPolicyService.php
* You can enable debug mode by invoking the script with '-d' as a parameter:
* # ./FlashPolicyService.php -d
* To stop the daemon, simply send it a SIGTERM and it should attempt to
* exit cleanly.
*
* If you get 'bad interpreter' errors or the like, change the #! line to
* reflect the actual installed location of your php cli.
*
* Configuration:
* At present, there aren't very many config options. Simply edit the
* section immediately following this header. Options are commented.
*
* License:
* This code is made available under a Creative Commons Attribution 3.0
* License. Basically, you can use it however you like, but I would
* appreciate some credit when you do.
*
* Disclaimer:
* I make no guarantees that this code won't make your server explode in a
* shower of blue flames. However, I don't expect that it will. I am actually
* confident that this code will be helpful.
*
* That said, this is still my beta release. If you find any bugs, please
* let me know so I can fix them.
*
* - Ammon Lauritzen [Apr 21, '08]
* http://ammonlauritzen.com/blog/2008/04/22/flash-policy-service-daemon/
*
* Changelog
* 0.9.c
* - Fixed some typoes that were the result of how I combined everything
* into a single file. Thanks Alex!
* 0.9.b
* - Original version to be posted at this url.
* 0.9.a
* - Original proof of concept code posted online.
*/
/*** Config ***/
// where should we save the log output?
$log_filename = "/tmp/flash-policy.log";
// uncomment these lines to choose which user to run the daemon as
// default behavior is to look up and attempt to run as 'nobody'
# $daemon_uid = 99;
# $daemon_gid = 99;
// set this if you want to use an external file in stead of the default
$xml_filename = "";
$default_xml =
'<'.'?xml version="1.0" encoding="UTF-8"?'.'>'.
'<cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd">'.
'<allow-access-from domain="*" to-ports="*" secure="false" />'.
'<site-control permitted-cross-domain-policies="all" />'.
'</cross-domain-policy>';
/*** You shouldn't have to edit anything below here ***/
/////////////////////////////////////////////////////////////////////////////
class Logger {
public function __construct($logfile) {
$this->logfile = $logfile;
$this->open_log();
}// end: constructor
public function __destruct() {
@fflush($this->fh);
@fclose($this->fh);
}// end: destructor
public function log($msg) {
// deal with redundant log spam
if($msg == $this->last_msg) {
$this->last_msg_count++;
return;
} else if($this->last_msg_count) {
$this->write("Last message repeated ".$this->last_msg_count." times.");
}
$this->lasg_msg = $msg;
$this->last_msg_count = 0;
// actually write the log message out
$this->write($msg);
}// end: log
private function write($msg) {
$msg = sprintf("[%s] %s\n",date("y-m-d H:i:s"),$msg);
$succ = @fwrite($this->fh, $msg);
if($succ === FALSE) {
echo $msg;
}
}// end: write
private function open_log() {
if(!file_exists($this->logfile)) {
touch($this->logfile);
chmod($this->logfile, 0664);
}
$this->fh = @fopen($this->logfile, "a");
}
}// end: logger class
/////////////////////////////////////////////////////////////////////////////
class Daemon {
public function __construct() {
error_reporting(0);
set_time_limit(0);
global $log_filename, $pid_filename;
$this->logger = new Logger($log_filename);
$this->pid_filename = $pid_filename;
$this->log_tag = $this->daemon_tag = "launcher";
$this->debug("constructed", $this->daemon_tag);
}// end: constructor
public function __destruct() {
$this->debug("destructing", $this->daemon_tag);
}// end: destructor
protected function log($msg, $tag = false) {
if($tag == false)
$tag = $this->log_tag;
$this->logger->log($tag.": ".$msg);
}// end: log
protected function debug($msg, $tag = false) {
if(DEBUG)
$this->log($msg, $tag);
}// end: debug
protected function main() {
$this->log("override main() in daemon subclass", $this->daemon_tag);
$this->stop();
}// end: main
public function start() {
$this->log("starting daemon", $this->daemon_tag);
if(!$this->_start()) {
$this->log("unable to start daemon", $this->daemon_tag);
return;
}
// report execution details
$this->log("uid = ".posix_getuid().", gid = ".posix_getgid());
$this->log("cwd = ".getcwd());
// invoke main loop
$this->running = true;
while($this->running) {
$this->main();
}
}// end: start
private function _start() {
if(!$this->_fork()) {
return false;
}// end: try to fork
if(!posix_setsid()) {
$this->log("unable to setsid()", $this->daemon_tag);
return false;
}// end: try to set sid
if(!$this->_suid()) {
return false;
}// end: try to set uid
// register signal handler
declare(ticks = 1);
pcntl_signal(SIGTERM, array(&$this, "on_sigterm"));
// chdir somewhere moderately safe by default
chdir('/tmp');
return true;
}// end: _start
private function _fork() {
$this->log("forking…", $this->daemon_tag);
$pid = pcntl_fork();
if($pid == -1) {
// error
$this->log("unable to fork", $this->daemon_tag);
return false;
} else if($pid) {
// parent
$this->debug("done with parent", $this->daemon_tag);
exit(0);
} else {
// child
$this->daemon_tag = "daemon";
$this->child = true;
$this->pid = posix_getpid();
$this->debug("child pid = ".$this->pid);
return true;
}
}// end: _fork
private function _suid() {
global $daemon_uid, $daemon_gid;
if(!isset($daemon_uid) || !isset($daemon_gid)) {
// we didn't get a uid/gid, try to make one up
$this->debug("searching for info on 'nobody'", $this->daemon_tag);
$res = posix_getpwnam("nobody");
if($res !== FALSE) {
$uid = $res['uid'];
$gid = $res['gid'];
} else {
// the 'nobody' user doesn't exist on this system, refuse
// to daemonize as root
$this->log("unable to find info on 'nobody' user", $this->daemon_tag);
return false;
}
} else {
$this->debug("got uid/gid of $daemon_uid/$daemon_gid", $this->daemon_tag);
$uid = $daemon_uid;
$gid = $daemon_gid;
}
// actually try to switch now
if(!posix_setgid($gid)) {
$this->log("unable to set gid to ".$gid, $this->daemon_tag);
return false;
} else if(!posix_setuid($uid)) {
$this->log("unable to set uid to ".$uid, $this->daemon_tag);
return false;
} else {
return true;
}
}// end: _suid
public function stop() {
$this->log("stopping daemon", $this->daemon_tag);
$this->running = false;
}// end: stop
protected function on_sigterm($sig) {
if($sig == SIGTERM) {
$this->log("got SIGTERM", $this->daemon_tag);
$this->stop();
exit(0);
}
}// end: on_sigterm
}// end: daemon class
/////////////////////////////////////////////////////////////////////////////
class FlashPolicyService extends Daemon {
public function __construct() {
parent::__construct();
$this->log_tag = "fps";
$this->debug("constructing");
$this->connections = array();
$this->request_str = "<policy-file-request/>";
$this->port = 843;
// get our xml
global $xml_filename, $default_xml;
if(strlen($xml_filename) == 0 || !file_exists($xml_filename)) {
$this->log("unable to read xml from '$xml_filename', using default");
$this->xml = $default_xml;
} else {
$this->log("reading policy xml from $xml_filename");
$this->xml = file_get_contents($xml_filename);
}
$this->debug("policy xml: ".$this->xml);
// make sure we're null terminated
$this->xml = trim($this->xml)."\n\0";
// and get going
$this->init();
}// end: constructor
public function __destruct() {
parent::__destruct();
if($this->sock)
@fclose($this->sock);
}// end: destructor
private function init() {
$this->debug("init…");
if($this->check_socket()) {
parent::start();
} else {
$this->log("not starting daemon");
}
}// end: init
protected function main() {
if($this->sock) {
while(true) {
$this->accept_socket();
}
} else {
$this->log("server socket is closed?!");
parent::stop();
}
// paranoia to keep from absolutely hosing cpu if something goes wrong
usleep(10000); // 10ms
}// end: main
private function check_socket() {
$this->sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if(!$this->sock) {
$this->log("unable to create socket");
} else {
$succ = @socket_bind($this->sock, "0.0.0.0", $this->port);
if(!$succ) {
$this->log("unable to bind to port ".$this->port);
} else {
$backlog = 100;
$succ = @socket_listen($this->sock, $backlog);
if(!$succ) {
$this->log("unable to listen with backlog of $backlog");
} else {
// everything's good
return true;
}
}// end: able to bind
}// end: able to create socket
// if we got here, it's an error. abort.
$errno = socket_last_error($this->sock);
$errstr = socket_strerror($errno);
$this->log("socket error: $errno: $errstr");
return false;
}// end: check_socket
private function accept_socket() {
$r_socks = array_merge(array($this->sock), $this->connections);
$this->debug("selecting on ".count($r_socks)." sockets");
// block until something interesting happens
$select = @socket_select($r_socks, $w_socks = NULL, $e_socks = NULL, NULL);
if(!$select)
return;
// did we get a new connection?
if(in_array($this->sock, $r_socks)) {
$conn = @socket_accept($this->sock);
if($conn !== false)
@socket_getpeername($conn, $addr);
$this->log("connection accepted from $addr, $conn");
$this->connections[] = $conn;
}// end: got a new connection
// check for policy requests
foreach($r_socks as $conn) {
// ignore the server socket
if($conn == $this->sock)
continue;
// read from the client
$data = @socket_read($conn, 1024);
if($data === FALSE) {
$this->log("got disconnect from $conn");
}// end: client closed connection
else {
$this->debug("read '".trim($data)."' from $conn");
if(strpos($data, $this->request_str) !== FALSE) {
$this->log("sending policy xml to $conn");
@socket_write($conn, $this->xml);
} else {
$this->log("got invalid request from $conn");
}
}// end: got data from the client
// and always disconnect after having read something, whether
// it was a valid request or not - especially if it wasn't ;)
@socket_close($conn);
$key = array_search($conn, $this->connections);
if($key !== FALSE)
unset($this->connections[$key]);
}// end: foreach socket
}// end: accept_socket
}// end: flash policy service class
/////////////////////////////////////////////////////////////////////////////
/**
* Actual execution code here. This checks if the php install has all of our
* requisite extensions, makes sure we're launching as root, and checks if
* debug mode was requested before actually starting the daemon.
*/
// make sure we have required extensions
$required_extensions = array("sockets", "posix", "pcntl");
$missing_extension = false;
foreach($required_extensions as $ext) {
if(!extension_loaded($ext)) {
echo "Missing required php extension '$ext'.n";
$missing_extension = true;
}
}
if($missing_extension) {
exit(1);
}
// make sure we launch as root, otherwise we can't bind to 843
if(posix_getuid() != 0 || posix_getgid() != 0) {
echo "Policy service must be started as root.n";
exit(1);
}
// see if we're in debug mode
define("DEBUG", in_array('-d',$argv));
// start the daemon
$fps = new FlashPolicyService();
?>
Therading is impossible in Flash. But:
LocalConnection between mutliple Flash embedded in same page ? (depend browser, but maybe all instance are in same os thread)ShaderJobs (fp10)Implementation of pseudo threading:
GreenThread//http://blogs.adobe.com/aharui/2008/01/threads_in_actionscript_3.html
package
{
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.utils.getTimer;
import flash.display.Sprite;
public class PseudoThread extends EventDispatcher
{
public function PseudoThread(parent:Sprite, threadFunction:Function, threadObject:Object):void
{
fn = threadFunction;
obj = threadObject;
// add high priority listener for ENTER_FRAME
parent.stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 100);
parent.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
parent.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
thread = new Sprite();
parent.addChild(thread);
thread.addEventListener(Event.RENDER, renderHandler);
}
// number of milliseconds we think it takes to render the screen
public var RENDER_DEDUCTION:int = 10;
private var fn:Function;
private var obj:Object;
private var thread:Sprite;
private var start:Number;
private var due:Number;
private var mouseEvent:Boolean;
private var keyEvent:Boolean;
private function enterFrameHandler(event:Event):void
{
start = getTimer();
var fr:Number = Math.floor(1000 / thread.stage.frameRate);
due = start + fr;
thread.stage.invalidate();
thread.graphics.clear();
thread.graphics.moveTo(0, 0);
thread.graphics.lineTo(0, 0);
}
private function renderHandler(event:Event):void
{
if (mouseEvent || keyEvent)
due -= RENDER_DEDUCTION;
while (getTimer() < due)
{
if (!fn(obj))
{
if (!thread.parent)
return;
thread.stage.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
thread.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
thread.stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
thread.parent.removeChild(thread);
thread.removeEventListener(Event.RENDER, renderHandler);
dispatchEvent(new Event("threadComplete"));
}
}
mouseEvent = false;
keyEvent = false;
}
private function mouseMoveHandler(event:Event):void
{
mouseEvent = true;
}
private function keyDownHandler(event:Event):void
{
keyEvent = true;
}
}
}