-
// this xml is inline but could easily be in an external file
-
var script:XML=<code>
-
-
<!-- // call some methods of the main timeline graphics property -->
-
<call method="graphics.beginFill" args="0xFF0000" />
-
-
<call method="graphics.drawRect" args="0, 0">
-
<!-- // use this to access properties of the main movie -->
-
<!-- // and use them as arguments -->
-
<arg reference="stage.stageWidth" />
-
<arg reference="stage.stageHeight" />
-
</call>
-
-
<call method="graphics.endFill" args=""/>
-
-
<call method="graphics.beginFill" args="0x0000FF">
-
<!-- //regular non-reference arguments can be passed like this -->
-
<arg value="0.5" />
-
</call>
-
-
<call method="graphics.drawCircle" args="100,100,20" />
-
-
<call method="customFunction" args="hello">
-
<arg reference="root.loaderInfo.bytesTotal" />
-
</call>
-
-
</code>
-
-
function customFunction(a:String, b:String):void{
-
trace("I am a custom function called from xml");
-
trace("Here is an argument: " + a);
-
trace("Here is another argument, (total bytes of this swf): " + b);
-
}
-
-
// parse and run
-
runCode(script);
-
-
function runCode(code:XML):void{
-
var children:XMLList = code.children();
-
for (var i:int = 0; i<children.length(); i++){
-
var child:XML = children[i];
-
var type:String = child.name();
-
if (type == "call"){
-
runMethod(child);
-
}
-
}
-
}
-
-
function runMethod(code:XML):void{
-
var i:int = 0;
-
// get a reference to the function
-
var method:Function = dotSyntax(code.@method);
-
// call the function if there are no arguments
-
if (code.@args.toXMLString().length == 0 && code.arg.length() == 0){
-
method();
-
}else{
-
-
var args:Array = code.@args.split(",");
-
var childArgsLength:int = code.arg.length()
-
for (i = 0; i<childArgsLength; i++){
-
// add another one with dot syntax
-
var val:String = code.arg[i].@value;
-
if (val){
-
args.push(val);
-
}
-
}
-
for (i = 0; i<args.length; i++){
-
if (args[i] != ""){
-
args[i] = valueType(args[i]);
-
}
-
}
-
for (i = 0; i<code.arg.length(); i++){
-
var rs:String = code.arg[i].@reference;
-
if (rs){
-
var ref:* = dotSyntax(rs);
-
args.push(ref);
-
}
-
}
-
// run the function
-
method.apply(null,args);
-
}
-
}
-
-
// parse dot syntax and return the last property or method
-
function dotSyntax(str:String):*{
-
var path:Array = str.split(".");
-
var curr:* = this;
-
for (var i:int = 0; i<path.length; i++){
-
curr = curr[path[i]]
-
}
-
return curr;
-
}
-
-
function valueType(val:*):* {
-
if (isNaN(Number(val))) {
-
// remove leading and trailing white
-
// remove "" around strings
-
val = val.replace(/^s+|s+$/g,"").replace(/^"|"$/g,"");
-
// see if it's a boolean
-
if (val == "true"){
-
val = true;
-
}else if (val == "false"){
-
val = false
-
}
-
} else {
-
val = Number(val);
-
}
-
return val;
-
}
WARNING: There area few small bugs in this snippet. If you'd like to use this, check out the AsXML mini-library
A few days ago I had the idea to write some code that would parse ActionScript from XML. The features that I realized would be possible are:
1) call methods of the main timeline
2) read and write properties on the main timeline
3) instantiate classes on the main timeline
4) call methods on these classes
5) read and write properties on these classes
So this morning I wrote the first part. This snippet has the ability to read an XML file and call methods accordingly. It also has the ability to read properties of the main timeline and pass them to these methods.
The XML in this snippet draws a box using the stageWidth and stageHeight. It draws a transparent circle and then calls a custom function. The custom function gets passed the root.loaderInfo.bytesTotal property.
I've done something similar a few times where I specifically targeted the Graphics API. This takes that to the next level by potentially working with any ActionScript classes (excluding Vector maybe... need to think about that).
I'll post another version with more features tomorrow. At the very least it will have class instantiation.