AARON SMITH’S CODE ENDEAVOR

Assets and the Model Class

Continuing on from Preloading and Asset Management. Let’s look at how the model can help with asset definitions, and removing hard coded assets.

The Model class in Guttershark is one of a couple “brains” in the library. It can do lots of stuff for you, but today, we’ll just focus on assets and paths. I’m going to continue using the example from Preloading and Asset Management - just adding and removing some code.

Before we get too far into this, make note of the PreloadController.addItems method. Notice that it takes an array of items (Asset instances).

Now take a look at these methods on the Model class. (getAssetByLibraryName, getAssetsByLibraryNames, getAssetGroup).

The Model class works with an XML object - which must be structured a certain way, then the model can do all this work for you.

To start getting this all setup, let’s first look at the most basic XML file, which defines some assets. This xml will show you how to use two of the model methods.

<?xml version="1.0" encoding="utf-8"?>
<model>
	<assets>
 
		<!-- for the model method, getAssetsByLibraryNames -->
		<asset libraryName="myPicture" src="assets/myPicture.jpg" />
		<asset libraryName="myOtherPicture" src="assets/myOtherPicture.jpg" />
 
		<!-- for the model method, getAssetGroup -->
		<group id="pictures">
			<asset libraryName="myPicture" src="assets/myPicture.jpg" />
			<asset libraryName="myOtherPicture" src="assets/myOtherPicture.jpg" />
		</group>
	</assets>
</model>

Ok, so with that in mind - here’s our first example of using this:

package
{
	import flash.events.Event;
	import flash.net.URLRequest;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import net.guttershark.control.PreloadController;
	import net.guttershark.support.preloading.Asset;
	import net.guttershark.support.preloading.events.PreloadProgressEvent;
	import net.guttershark.util.XMLLoader;
	import net.guttershark.model.Model;
 
	public class TestPreloader extends Sprite
	{
 
		private var ml:Model;
		private var am:AssetManager;
		private var pc:PreloadController;
		private var assets:Array;
		private var xmlLoader:XMLLoader;
		public var progress:MovieClip;
 
		public function TestPreloader()
		{
			am = AssetManager.gi();
			loadModelXML();
		}
 
		private function loadModelXML():void
		{
			xmlLoader=new XMLLoader();
			xmlLoader.contentLoader.addEventListener(Event.COMPLETE,onModelLoaded);
			xmlLoader.load(new URLRequest("model.xml"));
		}
 
		private function onModelLoaded(e:*):void
		{
			ml=Model.gi();
			ml.xml=new XML(xmlLoader.data);
 
			preloadAssets();
		}
 
		private function preloadAssets():void
		{
			pc = new PreloadController(300); //remember.. 300 = the pixelsToFill.
			pc.addEventListener(Event.COMPLETE,onPreloadComplete); //when preloading all items complete.
			pc.addEventListener(PreloadProgessEvent.PROGRESS,onProgress); //progress for all items as a whole.
 
			/* first way to get assets, using getAssetsByLibraryNames */
			assets = ml.getAssetsByLibraryNames("myPicture","myOtherPicture");
 
			/* second way, using groups */
			assets = ml.getAssetGroup("pictures");
 
			pc.addItems(assets);
			pc.start();
		}
 
		private function onPreloadComplete(e:Event):void
		{
			trace("preloading complete");
			addChild( am.getBitmap("myPicture") );
		}
 
		private function onProgress(ppe:PreloadProgessEvent):void
		{
			trace(ppe);
			progress.width=ppe.pixels;
		}
	}
}

It’s simple right? But wait, there’s more!

The model xml has some room for improvement - getting rid of the asset paths. For example, in the model xml, each asset defines the “src” attribute to equal something like: “assets/XXX”. It would be nice to not have to define that all the time. So how can we change it?


The Model and Paths

The Model class has two methods for working with paths. addPath and getPath.

Before we integrate these methods into the code, here’s a sand-boxed code example of how the path methods work:

var ml=Model.gi();
 
//the preferred way:
ml.addPath("root","http://example.com/");
ml.addPath("assets", ml.getPath("root")+"assets/") );
ml.adddPath("xml", ml.getPath("assets")+"xml/") );
trace( ml.getPath("xml") ); // http://example.com/assets/xml/
 
//but, you can also define just the pieces of a path, and use ...rest parameters with the getPath method.
ml.addPath("root","http://example.com/");
ml.addPath("assets","assets/");
ml.addPath("xml","xml/");
trace( ml.getPath("root","assets","xml") ); //http://example.com/asset/xml/

By convention, you should always add trailing slashes at the end of a path. This makes sure you never have to write parse code to remove double slashes (//), or testing to see if the index of a slash is the last character, etc.

That’s pretty easy right? We can integrate that into the model xml, and code.

Here’s the new model xml, note that I’m only going to use one style for grabbing assets - the group ids.

<?xml version="1.0" encoding="utf-8"?>
<model>
	<assets>
		<group id="pictures">
			<asset libraryName="myPicture" src="myPicture.jpg" path="bitmaps" />
			<asset libraryName="myOtherPicture" src="myOtherPicture.jpg" path="bitmaps" />
		</group>
	</assets>
</model>

Notice the new attribute, “path”. All of the methods on the Model class that help with getting you assets, will look for this path attribute, and then look in the model for path definitions that match that, and prepend it onto the src attribute.

Here’s our updated example:

package
{
	import flash.events.Event;
	import flash.net.URLRequest;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import net.guttershark.control.PreloadController;
	import net.guttershark.support.preloading.Asset;
	import net.guttershark.support.preloading.events.PreloadProgressEvent;
	import net.guttershark.util.XMLLoader;
	import net.guttershark.model.Model;
 
	public class TestPreloader extends Sprite
	{
 
		private var ml:Model;
		private var am:AssetManager;
		private var pc:PreloadController;
		private var assets:Array;
		private var xmlLoader:XMLLoader;
		public var progress:MovieClip;
 
		public function TestPreloader()
		{
			am = AssetManager.gi();
			loadModelXML();
		}
 
		private function loadModelXML():void
		{
			xmlLoader=new XMLLoader();
			xmlLoader.contentLoader.addEventListener(Event.COMPLETE,onModelLoaded);
			xmlLoader.load(new URLRequest("model.xml"));
		}
 
		private function onModelLoaded(e:*):void
		{
			ml=Model.gi();
			ml.xml=new XML(xmlLoader.data);
 
			/** define paths. **/
			ml.addPath("bitmaps","assets/bitmaps/");
 
			preloadAssets();
		}
 
		private function preloadAssets():void
		{
			pc = new PreloadController(300); //remember.. 300 = the pixelsToFill.
			pc.addEventListener(Event.COMPLETE,onPreloadComplete); //when preloading all items complete.
			pc.addEventListener(PreloadProgessEvent.PROGRESS,onProgress); //progress for all items as a whole.
 
			assets = ml.getAssetGroup("pictures");
 
			pc.addItems(assets);
			pc.start();
		}
 
		private function onPreloadComplete(e:Event):void
		{
			trace("preloading complete");
			addChild( am.getBitmap("myPicture") );
		}
 
		private function onProgress(ppe:PreloadProgessEvent):void
		{
			trace(ppe);
			progress.width=ppe.pixels;
		}
	}
}

There’s only one minor change to the code, I’ve added one line that defines the “bitmaps” path with the model.


Conclusion

That’s all there is to assets and paths with the model class. Hopefully you begin to see how much work Guttershark can really do for you. Guttershark is all about eliminating code. I hate writing code, don’t you? I actually love writing code, but the code that I hate writing is the same code i’ve already written on another project.

You may have noticed, there’s even more room for improvement. There are a few things here that should definitely not have to be written again. And there’s still a few things that are “hard coded”.

What I’ll show you next is the DocumentController. It takes care of loading your model xml, and gives you hooks to initialize paths with the model.

With Guttershark and the DocumentController, you’ll see that this example we’ve been working on will be significantly reduced - imagine that, event less code?

  

9 Comments so far

  1. [...] on from assets and the model, Let’s take a look at the [...]

  2. Joey July 31st, 2009 12:31 pm

    Your last example code has a few errors that prevent it from compiling. Perhaps you should test the code before posting it?

  3. admin July 31st, 2009 1:15 pm

    nah, i leave that up to the reader. The code I provide is off the top of my head. I’l mention that next time. -A

  4. admin July 31st, 2009 1:17 pm

    Also, if you use FDT it should catch any errors. Sorry!

  5. Mike November 24th, 2009 11:20 pm

    Thanks for these articles, they’ve been helpful. I’ve been doing object oriented AS3 for about a year now and I’ve learned quite a bit lately examining the Guttershark source. Thanks for putting all this out there.

  6. admin November 25th, 2009 12:23 am

    Mike, You are welcome! I’ve always believed reading source code is the best way to learn. Reading guttershark will be a good read. Thanks for your support!

  7. Marcy Sutton February 22nd, 2010 1:25 pm

    Does the Model XML structure have to be the same as above, or could Guttershark be used with a different XML structure? I have an entire website based on a single XML file, and am trying to figure out the best loading procedure. XML has to be loaded first, and then images (filenames are in the structure document). Not quite sure if Guttershark would be a good candidate.

  8. admin February 22nd, 2010 6:05 pm

    Hi Marcy,

    Guttershark uses a Model class, which expects the assets to be defined this way. But the only reason it has to be defined that way is because the Model class has helper methods (liek getAssetByLibraryName), which expects the xml formatted that way.

    But ultimately, what’s happening, is it’s returning an “Asset” instance (gs.support.preloading.Asset). The Preloader class has a method called “addItems”, which expects an array of Asset instances. So, like I said, it’s really just shortcuts so you don’t have to create asset instances manually.

    Nothing’s really tied together. I’d recommend reading some of those methods in the Model (getAssetByLibraryName, getAsset*). I think you’ll see that you can easily use your own xml. You just wouldn’t be able to use the shortcut methods that the Model class provides.

    Hopefull that helps.
    Aaron

  9. admin February 22nd, 2010 6:06 pm

    Marcy, btw, Guttershark was updated so some of the code in this example may or may not work. But please do checkout all the examples in the repository.

Leave a reply