oh, i have finally got it working
first, i add this bitmap data dictionary in the asset manager class,
private var mBitmapDatas:Dictionary;
mBitmapDatas = new Dictionary();
and then i prepared the add/get/remove functions by copying the original ones,
/** Returns a bitmap data with a certain name, or null if it's not found. */
public function getBitmapData(name:String):BitmapData
{
return mBitmapDatas[name];
}
/** Returns all bitmap data names that start with a certain string, sorted alphabetically.
* If you pass a result vector, the names will be added to that vector. */
public function getBitmapDataNames(prefix:String="", result:Vector.<String>=null):Vector.<String>
{
return getDictionaryKeys(mBitmapDatas, prefix, result);
}
/** Register a bitmap data under a certain name. It will be available right away. */
public function addBitmapData(name:String, bitmapData:BitmapData):void
{
log("Adding bitmap data '" + name + "'");
if (name in mObjects)
log("Warning: name was already in use; the previous bitmap data will be replaced.");
mBitmapDatas[name] = bitmapData;
}
/** Removes a certain bitmap data, optionally disposing its memory right away. */
public function removeBitmapData(name:String, dispose:Boolean=true):void
{
log("Removing bitmap data '"+ name + "'");
if (dispose && name in mBitmapDatas)
mBitmapDatas[name].dispose();
delete mBitmapDatas[name];
}
of course, the purge() function needs to be updated, too,
/** Removes assets of all types and empties the queue. */
public function purge():void
{
log("Purging all assets, emptying queue");
for each (var texture:Texture in mTextures)
texture.dispose();
for each (var atlas:TextureAtlas in mAtlases)
atlas.dispose();
mRawAssets.length = 0;
mTextures = new Dictionary();
mAtlases = new Dictionary();
mSounds = new Dictionary();
mXmls = new Dictionary();
mObjects = new Dictionary();
mByteArrays = new Dictionary();
mBitmapDatas = new Dictionary();
}
alright, after all these functions are ready, i began modifying the loadQueue() function,
var xmls:Vector.<XML> = new <XML>[];
var numElements:int = mRawAssets.length;
var currentRatio:Number = 0.0;
var timeoutID:uint;
// this is the new vector
var bitmapDataInfos:Vector.<Object> = new <Object>[];
we can then pass the vector to the function "processNext" as a temporary storage for the bitmap data of our loaded bitmap assets,
function processNext():void
{
var assetInfo:Object = mRawAssets.pop();
clearTimeout(timeoutID);
// i added the last "bitmapDataInfos" parameter
processRawAsset(assetInfo.name, assetInfo.asset, xmls, progress, resume, bitmapDataInfos);
}
now, i dig into the processRawAsset() function and save all the cloned bitmap data of every loaded bitmaps into the vector we just passed into this function,
// this is the updated function signature
private function processRawAsset(name:String, rawAsset:Object, xmls:Vector.<XML>, onProgress:Function, onComplete:Function, bitmapDataInfos:Vector.<Object>):void
// below is a section of code extracted from the function processRawAsset()
else if (asset is Bitmap)
{
// this is the only new line of code added
bitmapDataInfos.push( { key:name, data:(asset as Bitmap).bitmapData.clone() } );
texture = Texture.fromBitmap(asset as Bitmap, mUseMipMaps, false, mScaleFactor);
texture.root.onRestore = function():void
{
loadRawAsset(name, rawAsset, null, function(asset:Object):void
{
texture.root.uploadBitmap(asset as Bitmap);
asset.bitmapData.dispose();
});
};
asset.bitmapData.dispose();
addTexture(name, texture);
onComplete();
}
right, it is time for me to go back to the loadQueue() function, there is a function named processXmls() within the loadQueue() function,
function processXmls():void
{
// xmls are processed seperately at the end, because the textures they reference
// have to be available for other XMLs. Texture atlases are processed first:
// that way, their textures can be referenced, too.
xmls.sort(function(a:XML, b:XML):int {
return a.localName() == "TextureAtlas" ? -1 : 1;
});
for each (var xml:XML in xmls)
{
var name:String;
var rootNode:String = xml.localName();
if (rootNode == "TextureAtlas")
{
name = getName(xml.@imagePath.toString());
// my newly added code starts here
var bitmapData:BitmapData = null;
for (var idx:int = 0; idx < bitmapDataInfos.length; idx++)
{
if (bitmapDataInfos[idx].key == name)
{
bitmapData = bitmapDataInfos[idx].data;
break;
}
}
if (bitmapData != null)
{
var cacheBitmapData:Boolean = (xml.@cache.toString() == "true" ? true : false);
if (cacheBitmapData)
{
addBitmapData(name, bitmapData.clone());
}
bitmapData.dispose();
}
// my newly added code ends here
var atlasTexture:Texture = getTexture(name);
addTextureAtlas(name, new TextureAtlas(atlasTexture, xml));
removeTexture(name, false);
}
else if (rootNode == "font")
{
name = getName(xml.pages.page.@file.toString());
log("Adding bitmap font '" + name + "'");
var fontTexture:Texture = getTexture(name);
TextField.registerBitmapFont(new BitmapFont(fontTexture, xml));
removeTexture(name, false);
}
else
throw new Error("XML contents not recognized: " + rootNode);
System.disposeXML(xml);
}
}
and that's it! right now i can just add a "cache" property in my atlas xml file as follow,
<TextureAtlas imagePath="myAtlas.png" cache="true">
after the asset manager finished loading all the enqueued assets, i can extract my cached bitmap data now
there is still a question though, can i know the actual area or rectangular bound on the original spritesheet of a certain texture extracted from a texture atlas, so that i can use the bitmapdata of that area to run the "pixel perfect hittest"?
thanks