{"id":321,"date":"2009-06-20T11:35:11","date_gmt":"2009-06-20T18:35:11","guid":{"rendered":"https:\/\/actionsnippet.com\/?p=1595"},"modified":"2009-06-20T11:35:11","modified_gmt":"2009-06-20T18:35:11","slug":"xml-to-actionscript-2","status":"publish","type":"post","link":"https:\/\/actionsnippet.com\/?p=321","title":{"rendered":"XML to ActionScript #2"},"content":{"rendered":"<pre class=\"brush: as3; title: ; notranslate\" title=\"\">\r\nvar script:XML=&lt;code&gt;\r\n  \r\n   &lt;make reference=&quot;blur&quot; class=&quot;flash.filters.BlurFilter&quot;&gt;\r\n     &lt;set blurX=&quot;10&quot; blurY=&quot;10&quot; \/&gt;\r\n   &lt;\/make&gt;\r\n   \r\n   &lt;make reference=&quot;filts&quot; class=&quot;Array&quot;&gt;\r\n     &lt;call method=&quot;push&quot;&gt;\r\n\t   &lt;arg reference=&quot;blur&quot; \/&gt;\r\n\t &lt;\/call&gt;\r\n   &lt;\/make&gt;\r\n   \r\n   &lt;make reference=&quot;mat&quot; class=&quot;flash.geom.Matrix&quot;&gt;\r\n\t &lt;call method=&quot;rotate&quot; args=&quot;1&quot; \/&gt;\r\n\t &lt;set tx=&quot;100&quot; ty=&quot;100&quot; \/&gt;\r\n   &lt;\/make&gt;\r\n   \r\n   &lt;make reference=&quot;box&quot; class=&quot;flash.display.Sprite&quot; &gt;\r\n\t   &lt;setRef filters=&quot;filts&quot; transform.matrix=&quot;mat&quot;\/&gt;\r\n\t   &lt;call method=&quot;graphics.beginFill&quot; args=&quot;0x000000&quot; \/&gt;\r\n\t   &lt;call method=&quot;graphics.drawRect&quot; args=&quot;-50,-50,100,100&quot; \/&gt;\r\n   &lt;\/make&gt;\r\n   \r\n   &lt;call method=&quot;addChild&quot;&gt;\r\n     &lt;arg reference=&quot;box&quot;\/&gt;\r\n   &lt;\/call&gt;\r\n   \r\n   &lt;make reference=&quot;tf&quot; class=&quot;flash.text.TextFormat&quot;&gt;\r\n    &lt;set font=&quot;_sans&quot; size=&quot;12&quot; color=&quot;0xFFFFFF&quot; \/&gt;\r\n   &lt;\/make&gt;\r\n  \r\n   &lt;make reference=&quot;txt&quot; class=&quot;flash.text.TextField&quot; &gt;\r\n     &lt;setRef defaultTextFormat=&quot;tf&quot; \/&gt;\r\n     &lt;set autoSize=&quot;center&quot; text=&quot;XML to AS3&quot; \/&gt;\r\n   &lt;\/make&gt;\r\n  \r\n   &lt;make reference=&quot;circle&quot; class=&quot;flash.display.Sprite&quot; &gt;\r\n\t   &lt;set x=&quot;300&quot; y=&quot;300&quot; \/&gt;\r\n\t   &lt;call method=&quot;graphics.beginFill&quot; args=&quot;0xFF0000&quot; \/&gt;\r\n\t   &lt;call method=&quot;graphics.drawCircle&quot; args=&quot;0,0,100&quot; \/&gt;\r\n\t   &lt;call method=&quot;addChild&quot;&gt;\r\n         &lt;arg reference=&quot;txt&quot; \/&gt;\r\n       &lt;\/call&gt;\r\n   &lt;\/make&gt;\r\n   \r\n   &lt;call method=&quot;addChild&quot;&gt;\r\n     &lt;arg reference=&quot;circle&quot;\/&gt;\r\n   &lt;\/call&gt;\r\n  \r\n&lt;\/code&gt;\r\n\r\n\/\/ parse and run\r\nrunCode(this, script);\r\n\r\nfunction runCode(target:*, code:XML):void{\r\n\tvar children:XMLList = code.children();\r\n\tfor (var i:int = 0; i&lt;children.length(); i++){\r\n\t\tvar child:XML = children&#x5B;i];\r\n\t\tvar type:String = child.name();\r\n\t\tif (type == &quot;call&quot;){\r\n\t\t\trunMethod(target, child);\r\n\t\t}else if (type == &quot;set&quot;){\r\n\t\t\tsetProp(target, child);\r\n\t\t}else if (type == &quot;setRef&quot;){\r\n\t\t\tsetRefProp(target, child);\r\n\t\t}else if (type == &quot;make&quot;){\r\n\t\t\tmakeInstance(child);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction makeInstance(code:XML):void{\r\n\tvar ClassRef:Class = getDefinitionByName(code.@&#x5B;&quot;class&quot;]) as Class;\r\n\t\/\/ nothing can be passed to the class constructor\r\n\t\/\/ its not possible with function.apply\r\n\tvar instance:* = this&#x5B;code.@reference] = new ClassRef();\r\n\trunCode(instance, code);\r\n}\r\n\r\n\/\/ set a property to a reference\r\nfunction setRefProp(target:*, code:XML):void{\r\n\tvar attributes:XMLList = code.attributes();\t\r\n\tfor (var i:int = 0; i&lt;attributes.length(); i++){\r\n\t\tvar prop:String = attributes&#x5B;i].name();\r\n\t\tvar o:Object = dotSyntax(target, prop, 1)\r\n\t\tif (prop.indexOf(&quot;.&quot;) != -1){\r\n\t\t  o.obj&#x5B;o.prop] = dotSyntax(this, attributes&#x5B;i]);\r\n\t\t}else{\r\n\t\t  o.obj&#x5B;o.prop] = this&#x5B;attributes&#x5B;i]];\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\/\/ set a property to a value such as a Number, Boolean, String etc...\r\nfunction setProp(target:*, code:XML):void{\r\n\tvar attributes:XMLList = code.attributes();\t\r\n\tfor (var i:int = 0; i&lt;attributes.length(); i++){\r\n\t\tvar prop:String = attributes&#x5B;i].name();\r\n\t\tvar o:Object = dotSyntax(target, prop, 1)\r\n\t\to.obj&#x5B;o.prop] = valueType(attributes&#x5B;i]);\r\n\t}\r\n}\r\n\r\nfunction runMethod(target:*, code:XML):void{\r\n\tvar i:int = 0;\r\n\t\/\/ get a reference to the function\r\n\tvar method:Function = dotSyntax(target, code.@method);\r\n\t\/\/ call the function if there are no arguments\r\n\tvar attributeArgsLength:int = code.@args.toXMLString().length;\r\n\tvar childArgsLength:int = code.arg.length()\r\n\tif (attributeArgsLength == 0 &amp;&amp; childArgsLength == 0){\r\n\t\tmethod();\r\n\t}else{\r\n\t \r\n\t var args:Array;\r\n\t if (attributeArgsLength &gt; 0){\r\n\t\t args = code.@args.toString().split(&quot;,&quot;);\r\n\t } else {\r\n\t\targs = &#x5B;]; \r\n\t }\r\n\t\r\n\t for (i = 0; i&lt;childArgsLength; i++){\r\n\t\t  var val:String = code.arg&#x5B;i].@value;\r\n\t\t  if (val){\r\n\t\t    args.push(val); \r\n\t\t  }\r\n\t  }\r\n\t  for (i = 0; i&lt;args.length; i++){\r\n\t\t  if (args&#x5B;i] != &quot;&quot;){\r\n\t\t    args&#x5B;i] = valueType(args&#x5B;i]); \r\n\t\t  }\r\n\t  }\r\n\t  for (i = 0; i&lt;code.arg.length(); i++){\r\n\t\t var rs:String = code.arg&#x5B;i].@reference;\r\n\t\t if (rs){\r\n\t\t\t args.push(dotSyntax(this, rs));  \r\n\t\t }\r\n\t  }\r\n\t \r\n\t  \/\/ run the function\r\n\t  method.apply(null,args);\r\n\t}\r\n}\r\n\r\n\/\/ parse dot syntax and return the last property or method\r\nfunction dotSyntax(target:*, str:String, offset:int = 0):*{\r\n\tvar path:Array = str.split(&quot;.&quot;);\r\n\tvar curr:* = target;\r\n\tfor (var i:int = 0; i&lt;path.length - offset; i++){\r\n\t\tcurr = curr&#x5B;path&#x5B;i]]\r\n\t}\r\n\tif (offset != 0){\r\n\t\treturn {obj:curr, prop:path&#x5B;i]}\r\n\t}\r\n\treturn curr;\r\n}\r\n\r\nfunction valueType(val:*):* {\r\n    if (isNaN(Number(val))) {\r\n           \/\/ remove leading and trailing white\r\n           \/\/ remove &quot;&quot; around strings\r\n           val = val.replace(\/^s+|s+$\/g,&quot;&quot;).replace(\/^&quot;|&quot;$\/g,&quot;&quot;);\r\n           \/\/  see if it&#039;s a boolean\r\n           if (val == &quot;true&quot;){\r\n               val = true;\r\n           }else if (val == &quot;false&quot;){\r\n               val = false\r\n           }\r\n    } else {\r\n        val = Number(val);\r\n    }\r\n\treturn val;\r\n}\r\n<\/pre>\n<p><em>WARNING: There area few small bugs in this snippet. If you&#8217;d like to use this, check out the <a href=\"https:\/\/actionsnippet.com\/?p=1611\">AsXML mini-library<\/a><\/em><\/p>\n<p>This is the next version of yesterdays snippet. As you can see it isn&#8217;t really a snippet anymore&#8230; This code parses a specifically formatted xml file to allow the following features to be achieved from XML at runtime:<\/p>\n<p>1) call methods of the main timeline<br \/>\n2) read and write properties on the main timeline<br \/>\n3) instantiate classes on the main timeline<br \/>\n4) call methods on these classes<br \/>\n5) read and write properties on these classes<\/p>\n<p>By implement those five feature a great deal becomes possible. The above XML creates this somewhat crappy looking thing:<br \/>\n<img decoding=\"async\" src=\"https:\/\/actionsnippet.com\/wp-content\/xml2as3.gif\" \/><\/p>\n<p>While that doesn&#8217;t look like much, it&#8217;s actually doing quite a bit&#8230; It has a BlurFilter, an Array (for the filters property), two Sprites, a TextFormat and a TextField. addChild() is called on the main timeline and on one of the sprites (to nest the TextField in the circle).<\/p>\n<h2>Uses For This<\/h2>\n<p>You could use this to create levels for a simple game. <\/p>\n<p>You could generate this XML based on user input to create e-cards and mini-apps. <\/p>\n<p>If you have a medium sized app you could use it to create a sort of advanced config file that helps to ease your pain as the client decides they need 10 subtly different versions of the app. Every time the client decides they need a subtly different version you&#8217;d just need to create a different config file. THIS is probably the thing that I&#8217;ll be using it for &#8211; could be a huge time saver&#8230; <\/p>\n<h2>Uses With Libraries<\/h2>\n<p>This could be used with <a href=\"http:\/\/blog.greensock.com\/tweenliteas3\/\" target=\"blank\">TweenLite<\/a> and\/or <a href=\"http:\/\/blog.papervision3d.org\/\" target=\"blank\">Papervision<\/a>. You could just add a bunch of import statements to the timeline or to a dynamic document class. Then you&#8217;d be able to do some basic authoring from the XML. I think I&#8217;ll post an example of this either tonight or tomorrow.<\/p>\n<p>I did originally start writing this thinking about <a href=\"https:\/\/actionsnippet.com\/?page_id=1391\" target=\"blank\">QuickBox2D<\/a> &#8211; but I already have an editor for QuickBox2D that just needs some UI (currently its key controlled). So I don&#8217;t really need it. The QuickBox2D editor generates an ActionScript file &#8211; which makes sense because usually you need to go in and manually do a bunch of logic that couldn&#8217;t really be done easily with an editor. That said, this will work with Box2D or QuickBox2D as an XML format. <\/p>\n<h2>The Downside<\/h2>\n<p>The downside is that this is dynamic and is therefore untyped. All class instances created by reading the XML will be dynamically typed. For something where your only adding 10 classes this way, its no big deal &#8211; but for a game editor it could be a problem &#8211; at the very least there are interesting advanced techniques implemented in this snippet that could be repurposed for lots of different things.<\/p>\n<h2>More Examples<\/h2>\n<p>Tonight or tomorrow I&#8217;ll upload a few examples &#8211; it would be fun to do a TweenLite\/Papervision example&#8230; would also be good to show what I mean by an advanced config for a medium sized app.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>var script:XML=&lt;code&gt; &lt;make reference=&quot;blur&quot; class=&quot;flash.filters.BlurFilter&quot;&gt; &lt;set blurX=&quot;10&quot; blurY=&quot;10&quot; \/&gt; &lt;\/make&gt; &lt;make reference=&quot;filts&quot; class=&quot;Array&quot;&gt; &lt;call method=&quot;push&quot;&gt; &lt;arg reference=&quot;blur&quot; \/&gt; &lt;\/call&gt; &lt;\/make&gt; &lt;make reference=&quot;mat&quot; class=&quot;flash.geom.Matrix&quot;&gt; &lt;call method=&quot;rotate&quot; args=&quot;1&quot; \/&gt; &lt;set tx=&quot;100&quot; ty=&quot;100&quot; \/&gt; &lt;\/make&gt; &lt;make reference=&quot;box&quot; class=&quot;flash.display.Sprite&quot; &gt; &lt;setRef filters=&quot;filts&quot; transform.matrix=&quot;mat&quot;\/&gt; &lt;call method=&quot;graphics.beginFill&quot; args=&quot;0x000000&quot; \/&gt; &lt;call method=&quot;graphics.drawRect&quot; args=&quot;-50,-50,100,100&quot; \/&gt; &lt;\/make&gt; &lt;call method=&quot;addChild&quot;&gt; &lt;arg reference=&quot;box&quot;\/&gt; &lt;\/call&gt; &lt;make reference=&quot;tf&quot; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,88,55,34],"tags":[3,14,4],"class_list":["post-321","post","type-post","status-publish","format-standard","hentry","category-dynamic","category-external-data","category-instantiation","category-xml","tag-actionscript","tag-as3","tag-flash"],"_links":{"self":[{"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/posts\/321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=321"}],"version-history":[{"count":0,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/posts\/321\/revisions"}],"wp:attachment":[{"href":"https:\/\/actionsnippet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}