Filed under Programming

Runtime Stack Information for Logging and Debugging

by

Or, “Hack Your Stack for Fun and Profit!” Yes, this is really and truly a hack, my friends, but, like many hacks, you might find it very useful. Using the Stack class I provide, you can get all sorts of information about the code being run right now: the package, class name, method, filename, and even the line number. You can also grab an Array version of a stack trace and follow it up. Sweet!

So check out this egregious hack. First, you grab the stack trace by throwing and catching a dummy Error and copping its stack trace as a string. Note, that this technique only works (and is only useful) in the Debug Player.

public static function getRawStackTrace():String
{
	var stackTrace:String;
	try
	{
		throw new Error();
	} catch (error:Error) {
		stackTrace = error.getStackTrace();
	}
	return stackTrace;
}

Then you slice it up into lines, and hack those lines into their constituent parts by some crazy regular expressions. That’s pretty much it.

public static function getPartsFromStackTraceEntry(stackEntry:String):Object
{
	return stackEntry.match(/(?P<package>[\w\d\.]+)::(?P<classname>[\w\d\.\:]*?)(?P<isStatic>\$?)\/((?P<scope>[\w\d\.\:]+)::)?(?P<method>[\w\d]+\(\))(\[(?P<filename>[\w\d\\\/\.]+):(?P<line>\d+)\])?/);
}

Fun, right? The properties in the returned Object are:

  • package
  • classname
  • isStatic
  • scope
  • method
  • filename
  • line

You can clean this up into package.classname::method with getSimplifiedStackTraceEntry().

So that’s it, it’s just some regular expressions, but with this hack you can pull out all kinds of juicy information about the context your code is running in. It can be useful for your own debugging, logging, and error reporting.

filecom.yourmajesty.debug.Stack View Source | Download (.as, 2k)

Cylinder Mapping

by

At Your Majesty, we worked on a site where some images appear on different products. I had my hands full with the image generation backend and the hosting issues to work too much on the Flash, but I was able to contribute one effect. I wrote a cylindrical mapping class which let us put any image on a mug as it rotated in three-space.

The process for building this was actually kind of interesting. I ended up actually using that graphing calculator that comes with OS X to preview different equations. I figured, if I could visualize the cross-section of the cylinder across the axis of distortion, then I would have an appropriate function to generate the distortion for each pixel, so I plotted a bunch of different equations interactively without coding them up. For the vertical displacement, the curve of the top lip (and the entire front) of a mug looks like a semicircle, perhaps squashed, so I quickly ended up the equation for a circle, y² + x² = r or y = ±√(r – x²). However, the sides are a bit more exaggerated.

Word to first-time displacement map users like myself, using the drawing API’s gradient tool as a source for displacement map data is not going to yield very good effects, since it seems that it only interpolates between colors linearly, which won’t do much more than shear your image.

So here’s the effect applied to my banner. Scrub the mouse left to right below to “rotate” the “cylinder.” You can see that while the speed of the effect of course scales with the size of the distortion map, it is very fast.

If you see this message, you need to install Flash Player 9.

The code isn’t all cleaned up but at least the interface is clean. We simply create a new distortion map with a size and a display object to attach, set some parameters, and attach its ‘wet’ output to our display list.

map = new CylinderMap(200, 200, new IMAGE());
map.sideCompression = 100;
map.arc = -0.3;
map.rotation = 100;
addChild(map.wet);

And here’s the code for the displacement map class.

filecom.yourmajesty.effects.distortion.CylinderMap View Source | Download (.as, 5k)
filecom.yourmajesty.effects.distortion.IDistortionMap View Source | Download (.as, 1k)

ActionScript 3.0 Bible Available Now

by

View this article in other languages:

After nearly a year in development I’m very proud to announce that the ActionScript 3.0 bible has hit the shelves. This is our first book and its very exciting for us. The AS3 Bible is not just an update to the previous edition, the Flash 8 ActionScript Bible, but was written from the ground up with ActionScript 3.0 development in mind. We tried to focus on topics that matter to real world developers and to make it just as useful for experienced AS2 developers as it is for beginning programmers.

We’ve put a lot into this book and sincerely hope you enjoy it.

Get it at Amazon

NOTE: many people have been complaining about the lack of code on the companion site. We’re currently working with our publisher to get that sorted out as soon as possible and hopefully it should be up by the end of the week.

Mims with Bible

I asked a passing hobo to pose for a picture with the new Bible

My first Hydra

by

hydraPosterizeSample

If you watched the video from our previous post, you no doubt have heard of Hydra and AIF – the new image processing language for Adobe products including Astro. I’ve since downloaded the AIF Toolkit and played around with it and found it’s surprisingly simple. I made my first Hydra patch which is admittedly basic but only took me about half an hour to put together. Check it out below!

Posterize

Embed Almost Anything in Your SWF

by

Using mxmlc / Flex Builder, you can safely store any kind of binary data, text, or XML directly in your SWF if loading it at runtime is not possible or not desirable. Find out how below.

The Setup

My friend EJ was wondering if there was some way to compile XML directly into an application without putting it inline in code. Of course E4X allows you to type XML literals, but doing so with large blocks of XML can be problematic for a few reasons. You can’t edit this XML with an XML editor. The XML parsing inside Flex Builder can be faulty on occasion, causing ActionScript in the same file to be misinterpreted. Placing XML in your source files can make them unwieldy and large, and slow to parse.

An Idea, but Not the Right One

My initial idea was to use include. Even though #include is deprecated in AS3, the little-known include (no hash mark!) uses the same syntax and can include code in much the same way. The Flex framework uses this to include a common version number as a static field in many classes:

mx_internal static const VERSION:String = "3.0.0.0";

This line, found in the file Version.as is placed in the class definition of classes where include "Version.as" is found. However, you can’t just include arbitrary copy. The included code has to be one or more full lines. So my idea of using

protected var xml:XML =
include "static.xml"
;

wasn’t going to work. It did work when I included the whole variable declaration in the XML file, but then the file wasn’t valid XML any more! Not even close. And not too much better than just typing inline.

The Solution

The solution here is much, much more powerful than the original hack might have been. The MXML and AS3 compiler, mxmlc, which is used by Flex Builder as well, has the ability to embed all kinds of video, graphics, other swfs, and fonts into a SWF. The [Embed] metadata tag / compiler directive works whether you are using Flex or simply AS3. [Embed] associates a bit of data with a class that is capable of representing it.

If you haven’t seen it used before, here’s a simple example where we embed an image in the SWF:

[Embed(source="assets/photo.jpg")]
private const PhotoImage:Class;

And then you can use it:

var myPhoto:DisplayObject = DisplayObject(new PhotoImage());

So, I don’t know how Adobe is really implementing things under the hood, but I say the following with some certainty. The compiler, happening across your [Embed] directive, retrieves the source, and examines it to see what kind of file it is. Depending on the type of file you’ve asked the compiler to embed, the runtime class reference will produce a subclass of a particular kind of class which is appropriate for the data you’ve embedded. The compiler will take the source of that file, transcode it, preparing the data to be inlined in the SWF itself, and possibly preprocessing it, for example parsing SVG into vector shapes.

You should also know that depending on whether you’re using the Flex framework or not, I believe you will end up with different superclasses associated with your embedded assets. If you use Flex, you might see a FontAsset subclass where you would simply get a Font subclass were you only using ActionScript.

You can also embed SWFs and symbols from within SWFs, a technique I quite like. Simply use a symbol attribute in the compiler directive:

[Embed(source="MenuAssets.swf", symbol="com.partlyhuman.assets.TopMenuItem")]
protected const TopMenuItem:Class;

addChild(Sprite(new TopMenuItem()));

The transcoder should automatically know what to do with these kinds of assets:

  • JPG/JPEG image files
  • GIF image files
  • PNG image files
  • SVG/SVGZ vector image files (supports a subset of SVG 1.1)
  • MP3 sound files
  • TTF font files
  • Installed system fonts
  • SWF files and specific symbols inside SWFs

No, I Know What I’m Doing, Really

But get this! There are more things you can convince the transcoder to accept. By manually specifying the MIME type of the file, you can force the transcoder to interpret the data in some format. This is the solution to embedding any XML at compile time, and then some. In fact, you can embed any binary data you want in a SWF, as long as you know how to interpret it on the other side.

There may be additional interesting MIME types that are registered by the transcoder. These are, as far as I know, undocumented, so if you find an interesting one that’s not covered by the types above or these two introduced here, leave a comment.

Here, we see that we can import an XML file with MIME type text/xml, and it embedded as a subclass of XML.

[Embed(source="test.xml", mimeType="text/xml")]
protected const EmbeddedXML:Class;

var x:XML = XML(new EmbeddedXML());
trace(x.toXMLString()); //it should work!

To get this to work, you should keep the XML prolog in your XML file. With this technique, EJ didn’t have to load the XML asynchronously, it was embedded right in his SWF for instant access, binary compression, and easy deployment, and tight coupling with the build itself. He could also now use a normal, full-featured XML editor to mess with the XML source.

But it gets better! You can embed any binary data whatsoever in a SWF, as long as you know how to interpret it on the way out. To do this, use the directive to embed any file with MIME type application/octet-stream (an octet is just a fancy word for a byte, by the way, as a byte is eight bits, so a stream of octets is a fancy way of saying “a bunch of bytes”). The class comes out in ActionScript as a subclass of, can you guess? ByteArray!

Here, ActionScript genius Max knows how to parse a WAD file, which Doom and other ID games used for levels and sprites and all kinds of business. He puts it right in the SWF by embedding it as application/octet-stream and interpreting it as a ByteArray:

public class DoomTest extends Sprite {
    [Embed(source="doom1-shareware.wad", mimeType="application/octet-stream")]
    private const DoomWad:Class;

    public function DoomTest() {
        var wad:ByteArray = new DoomWad() as ByteArray;
        new DoomCore(this,wad);
    }
}

(Full source here) And, passing it to his Doom playing engine, you start playing the shareware level of Doom that was embedded right in the SWF!

You can apply this technique to any binary data you’ve cleverly figured out how to parse. Of course, Flash knows very well how to parse all the file types described in the list above, but with some creative coding, that’s just the beginning!