-
// 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.
6 Comments
Hi,
Interesting stuff. How do you foresee this being used? I’ve developed a toolkit around a similar idea for designing and populating websites/applications for my own company; it’s similar in spirit to what you’re doing here, and affords integration with content management systems.
Keep up the good work!
Hey Chris,
Since this snippet only has the ability to run a function it isn’t extremely useful. With all the features implement however (see features listed above) it could be used for a few different things… tomorrow I’m going to post the snippet that implements all these features and I’ll go into more detail… but this could be used as a sort of advanced config file for a medium sized app - it could be used to define levels for a game and (as you mentioned) could be used with some sort of cms… it could also be a good basis for a debugger utility… be sure to check out tomorrows post, I’ll try to go into more detail and may create a few demo files…
I’ve been scouring the interwebs for an xml based map editor for box2d in flash. It seems this may be where you are headed. Thanks for sharing your work with us - I’ve really enjoyed the posts.
Well the version I posted today will work for that. Could be a bit tedious though - also anything instantiated with this code will be dynamically typed.
I haven’t looked at it, but I think this thing called Box2DWith does xml based instantiation. Have a look at it here:
http://personal.boristhebrave.com/project/box2dwith/?q=project/box2dwith
I created an editor for my QuickBox2D library - in that you can just draw everything and it saves out an ActionScript file - but I won’t be uploading that for awhile as it still has some bugs and needs UI.
Good stuff. It seems that a lot of developers are reinventing the wheel.
Me personally wrote a not-so-small IoC framework based on Spring which actually does something like you did with this code but more advanced.
Nice blog btw, checked some posts.
Thanks Valentin… your IoC thing sounds cool… did you see the slightly more advanced version of this?.. here:
http://actionsnippet.com/?p=1611