S3d AssetsLibrary

author:
narongrit kanhanoi
description:
singleton texture manager use contentScaleFactor to choose HD or SD textures and easy config by XML (AIR only because used FileStream to load texture)
lastupdate:
2012-06-13
compatible:
v1.1
tag:
texture, contentScaleFactor
homepage:
http://heart.github.com/AssetLibrary/
download:
http://heart.github.com/AssetLibrary/
comment this extension:
http://forum.starling-framework.org/topic/assetslibrary-extension

Overview

AssetsLibrary is a extension help you to manage Assets eg. loadAsset dispose or use TextureAtlas reuse texture and automatic choose HD or SD texture by new property contentScaleFactor (new feature starling 1.1) read at http://wiki.starling-framework.org/manual/multi-resolution_development

download example project and source : https://github.com/heart/AssetLibrary

1.create folder for your texture

x1 is SD Texture

x2 is HD texture

2.create Library.xml like this

<?xml version="1.0" encoding="utf-8" ?>
<data>
 
	<directory scale="1" path="x1"/>
	<directory scale="2" path="x2"/>
 
	<image name="texture1" src="packerProject.png" xml="packerProject.xml" type="atlas" />
	<image name="texture2" src="image.png" type="image" />
 
</data>

you can config directory path 1x or 2x texture scale match value from contentScaleFactor if contentScaleFactor not match any directory will use first directory by default

3.your Starling Main Class

package{
import starling.display.Sprite;
import starling.extensions.s3d.AssetsLibrary;
 
public class Game extends Sprite{
public function Game()
		{
			AssetsLibrary.initLibrary("Library.xml");
 
			AssetsLibrary.prepareTextures(["texture1" , "texture2" ],onComplete);
 
		}
}
}

Look at

AssetsLibrary.initLibrary("Library.xml");

*for load your library xml but not start load texture yet call this function 1 time in your game

//start loading texture  array is your texture name in XML
AssetsLibrary.prepareTextures(["texture1" , "texture2" ],onComplete);

*you must call this function before your game code for start loading texture it will read contentScaleFactor for choose dirctory and automatic create Texture or TextureAtlas from attribute type from your XML

don't worry when you call prepareTextures function repeatedly for same texture it will ignore when found the old texture from pool (reuse texture)

<image name="texture1" src="packerProject.png" xml="packerProject.xml" type="atlas" />
<image name="texture2" src="image.png" type="image" />

when finish it will call onComplete function

4.get the texture or TextureAtlas

//normal texture
var texture:Texture = AssetsLibrary.getTexture("texture2") as Texture;
 
//atlas
var atlas1:TextureAtlas = AssetsLibrary.getTexture("texture1") as TextureAtlas;
atlas1.getTexture("greenCat");

5.and when you want to dispose texture

AssetsLibrary.disposeTextures(["texture1" , "texture2"]);

6.Complete Code

package  sample
{
 
	import starling.display.Image;
	import starling.display.Sprite;
	import starling.events.Touch;
	import starling.events.TouchEvent;
	import starling.events.TouchPhase;
	import starling.extensions.s3d.AssetsLibrary;
	import starling.textures.Texture;
	import starling.textures.TextureAtlas;
	/**
	 * ...
	 * @author narongrit@3dsinteractive.com
	 */
	public class Game extends Sprite
	{
		private var cat1:Image;
		private var cat2:Image;
		private var cat3:Image;
		private var cat4:Image;
		private var img1:Image;
		private var big:Image;
 
		public function Game()
		{
			AssetsLibrary.initLibrary("Library.xml");
 
			AssetsLibrary.prepareTextures(["texture1" , "texture2" ],onComplete);
 
		}
 
 
 
		private function onComplete():void
		{
 
			// Image Texture
			var texture:Texture = AssetsLibrary.getTexture("texture2") as Texture;
			img1 = new Image(texture);
			addChild(img1);
 
			//AtlasTexture
			var atlas1:TextureAtlas = AssetsLibrary.getTexture("texture1") as TextureAtlas;
 
			var greenCat:Texture = atlas1.getTexture("greenCat");
			var orangeCat:Texture = atlas1.getTexture("orangeCat");
			var redCat:Texture = atlas1.getTexture("redCat");
			var yellowCat:Texture = atlas1.getTexture("yellowCat");
 
			cat1 = new Image(greenCat);
			cat2 = new Image(orangeCat);
			cat3 = new Image(redCat);
			cat4 = new Image(yellowCat);
 
			addChild(cat1);
			addChild(cat2);
			addChild(cat3);
			addChild(cat4);
 
			cat1.x = 0;
			cat2.x = 50;
			cat3.x = 100;
			cat4.x = 150;
			//============
 
			this.addEventListener(TouchEvent.TOUCH , onTouch );
		}
 
		private function onTouch(e:TouchEvent):void
		{
 
			var t:Touch = e.getTouch(this, TouchPhase.BEGAN);
			if (t) {
				this.removeEventListener(TouchEvent.TOUCH , onTouch );
 
				trace('dispose all texture');
 
				removeChild(cat1 , true);
				removeChild(cat2, true);
				removeChild(cat3, true);
				removeChild(cat4, true);
				removeChild(img1, true);
 
				removeChild(big,true);
				AssetsLibrary.disposeTextures(["texture1" , "texture2"]);
			}
 
		}
 
 
	}
}

Changelog

  • 2012/06/12 13:58:
  • First public version ( sorry for my english i'm not good english )
  • 2012/07/9 17:36:
  • Fix Bug (prepare texture not call callback function (thanks Martin Dubois and Muller)

User Comments

Feel free to edit this part of the page!

Message from Martin Dubois on June 28th

First off, good job for the library. I was on to create something similar when I found out about S3d AssetsLibrary which works great. The only problem I encountered what that if all textures are already loaded, the prepareTextures callback doesn't get called.

I fixed the problem by changing the prepareTextures function of the Libraryclass as such in order to manually call the callback if all textures are already cached:

public function prepareTextures( textureName:Array, onComplete:Function ):void {
	var loader:AssetsLoader = new AssetsLoader( textureName , onComplete);
	if(loader.textures){
		loader.addEventListener(Event.COMPLETE , loadTextureComplete );
	}else {
		onComplete();
	}
}

Keep up the good work and thanks again!


Message from Mate Muller on July 07th

Nice work and a great extension, especially thanks for using the Texture.fromBitmap and contentScaleFactor!

Just a little bug in the Library.as :

public function disposeTextures(textureName:Array):void {
	var lenght:int = textureName.length;
	for (var i:int = 0; i < length ; i++ ) {
		if ( textureExist(textureName[i])  ) {
			textureDic[textureName[i]].dispose();
			delete textureDic[textureName[i]];
		}
	}
}

Misspelled lenght variable name, and the result is 1 (from the Object class) in the for loop. So it's deleting only the first element from the array.


Message from nkheart on July 9th

thankyou i fixed bug above


Message from Erwin Poerwanto on July 12th

Nice extension & thank you for your work !

But, I have a problem to access the assets file from parent directories or using the DotDot parameter like (“../../picture.jpg”) !!!

I have tried to change the code like this, and it's work :

In the Library.as :

var file:File = File.applicationDirectory.resolvePath(xmlFile);

Change the code to :

var file:File = new File(File.applicationDirectory.nativePath).resolvePath(xmlFile);

and

in the AssetsLoader.as :

imageFile = File.applicationDirectory.resolvePath( library.texturePath+"/"+library.xml.image.(@name == textureName[i]).@src );
 
xmlFile = File.applicationDirectory.resolvePath( library.texturePath+"/"+library.xml.image.(@name == textureName[i]).@xml );

to

imageFile = new File(File.applicationDirectory.nativePath).resolvePath(library.texturePath+"/"+library.xml.image.(@name == textureName[i]).@src);
 
xmlFile = new File(File.applicationDirectory.nativePath).resolvePath(library.texturePath+"/"+library.xml.image.(@name == textureName[i]).@xml);
  extensions/s3d_assetmanager.txt · Last modified: 2015/03/11 14:05 (external edit)
 
Powered by DokuWiki