Skip to content

Instantly share code, notes, and snippets.

@PsichiX
Last active August 29, 2015 14:22
Show Gist options
  • Save PsichiX/a0e6efdb9920fe58e39b to your computer and use it in GitHub Desktop.
Save PsichiX/a0e6efdb9920fe58e39b to your computer and use it in GitHub Desktop.
Awesome AssetManager API explanation
var assets,
assetRef,
assetRefClone,
assetRefs;
// custom asset class that inherit from AssetManager.Asset class.
function TextAsset(manager, id, config){
AssetManager.Asset.call(this, manager, id, config);
var source = config.source;
if (typeof source === 'string'){
// always load file from constructor, because constructor is called always
// when we acquire asset that does not exists.
this.load(source, AssetManager.Asset.LOADER_TYPE.TEXT);
} else {
console.error('TextAsset | `source` parameter has unknown data format!');
}
}
TextAsset.prototype = Object.create(AssetManager.Asset.prototype);
TextAsset.prototype.constructor = TextAsset;
// create manager.
assets = new AssetManager();
// register asset factory. params: type ID, asset class constructor, file extensions array.
assets.registerFactory('test.text', TextAsset, ['json']);
// acquire asset from file.
// protocols ('file://') are used to specify asset source.
// available protocols:
// file (path relative to application or web file (with 'http://')),
// id (registered assets),
// vars (variants logical expressions).
// to access assets we use asset reference object - it's not asset itself,
// but it's user-asset interface. asset reference have some great advantage:
// with that we can completely manage asset life-cycle.
// when we acquire asset, we got it's reference object,
// so to release asset from memory, we just destroy reference.
// example: if we acquire asset in two different places, we have two asset references
// and to remove asset from memory, we have to destroy those two references.
// why it's better than just keeping assets ref-counted? because if we release
// asset twice at one time, it will release asset, so asset reference objects are
// solution for accidentialy asset releasing.
assetRef = assets.acquire('file://assets/config.json');
// bind callbacks.
// when we bind callbacks on loading, they are called when assetRef.state is READY
// or ERROR respectively and will be unbind after that automatically.
// when we bind callbacks on ready or error, they are called directly.
assetRef.onComplete(function(){
console.log('loading from file complete: ' + this.data);
});
assetRef.onError(function(){
console.error('loading from file error!');
});
// clone asset - it returns new asset reference pointing to the same asset
// and now asset have two references pointing at asset.
assetRefClone = assetRef.clone();
// after destroying clone, asset will have one reference.
assetRefClone.destroy();
// and now asset does not have any references so it will be released from memory.
assetRef.destroy();
// register asset under given ID. params: asset ID, asset file path, type ID
// (or null - will be determined by file extension), variants array (or null).
assets.registerAsset('config', 'assets/config.json', null, ['text', 'test']);
// acquire asset from registered ID.
assetRef = assets.acquire('id://config');
assetRef.onComplete(function(){
console.log('loading from id complete: ' + this.data);
});
assetRef.onError(function(){
console.error('loading from id error!');
});
assetRef.destroy();
// acquire assets from variants. all registered assets that match
// requested variants expression will be acquired and array of
// asset references will be returned.
assetRefs = assets.acquire('vars://text & test');
assetRef = assetRefs[0];
aseetRefPaths = null;
assetRef.onComplete(function(){
console.log('loading from variants complete: ' + this.data);
});
assetRef.onError(function(){
console.error('loading from variants error!');
});
assetRef.destroy();
// remember: ALWAYS destroy manager (and every asset reference)
// when is no longer needed! This will keep application away from memory leaks!
assets.destroy();
var namespace = require('./module.js'),
AssetManager = namespace.AssetManager,
status,
assets,
assetRef,
assetRefClone,
assetRefs;
function TextAsset(manager, id, config){
AssetManager.Asset.call(this, manager, id, config);
var source = config.source;
if (typeof source === 'string'){
this.load(source, AssetManager.Asset.LOADER_TYPE.TEXT);
} else {
console.error('TextAsset | `source` parameter has unknown data format!');
}
}
TextAsset.prototype = Object.create(AssetManager.Asset.prototype);
TextAsset.prototype.constructor = TextAsset;
test.case('AssetManager')
.step('Check type', function(){
test(AssetManager instanceof Function, true, 'AssetManager is not type of Function');
test(AssetManager.Asset instanceof Function, true, 'AssetManager.Asset is not type of Function');
test(AssetManager.AssetRef instanceof Function, true, 'AssetManager.AssetRef is not type of Function');
this.success();
}).step('Create manager', function(){
assets = new AssetManager();
test(assets instanceof AssetManager, true, '`assets` is not type of AssetManager');
test(assets.getAssetsIDs() === null, false, 'AssetManager.getAssetsIDs() returns null!');
test(assets.getAssetsIDs().length, 0, '`assets` has assets!');
test(assets.getAssetsRegistryIDs() === null, false, 'AssetManager.getAssetsRegistryIDs() returns null!');
test(assets.getAssetsRegistryIDs().length, 0, '`assets` has registered assets!');
test(assets.getFactoriesRegistryIDs() === null, false, 'AssetManager.getFactoriesRegistryIDs() returns null!');
test(assets.getFactoriesRegistryIDs().length, 0, '`assets` has registered factories!');
this.success();
}).step('Register asset factory', function(){
status = assets.registerFactory('test.text', TextAsset, ['json']);
test(status, true, 'Cannot register TextAsset as asset factory!');
test(assets.getFactoriesRegistryIDs().length, 1, '`assets` does not have one registered factory!');
test(assets.getFactoriesRegistryIDs()[0], 'test.text', '`assets` does not have registered `test.text` asset factory!');
this.success();
}).step('Acquire asset from file', function(){
var self = this;
assetRef = assets.acquire('file://assets/config.json');
test(assetRef === null, false, '`assetRef` is null!');
test(assetRef instanceof AssetManager.AssetRef, true, '`assetRef` is not type of AssetManager.AssetRef!');
test(assetRef.isValid(), true, '`assetRef` is not valid!');
test(assetRef.manager, assets, '`assetRef.manager` is not `assets`!');
test(assetRef.id, 'assets/config.json', '`assetRef.id` is not the same as resource path!');
test(assetRef.data, null, '`assetRef.data` is not null!');
test(assetRef.state, AssetManager.Asset.STATE.LOADING, '`assetRef.state` is not loading!');
test(assetRef.assetUnsafe === null, false, '`assetRef.assetUnsafe` is null!');
test(assetRef.assetUnsafe instanceof TextAsset, true, '`assetRef.assetUnsafe` is not type of TextAsset!');
test(assets.getAssetsIDs().length, 1, '`assets` does not have one asset!');
test(assets.getAssetsIDs()[0], 'assets/config.json', '`assets` does not have asset `assets/config.json`!');
assetRef.onComplete(function(){
testAsync(assetRef.data === null, false, '`assetRef.data` is null!');
testAsync(typeof assetRef.data, 'string', '`assetRef.data` is not type of object!');
testAsync(assetRef.state, AssetManager.Asset.STATE.READY, '`assetRef.state` is not ready!');
self.success();
});
assetRef.onError(function(){
self.failure('asset cannot be loaded: file://assets/config.json');
});
}).step('Clone asset reference', function(){
test(assetRef.refCount, 1, '`assetRef.refCount` is not equal to 1!');
assetRefClone = assetRef.clone();
test(assetRefClone === null, false, '`assetRefClone` is null!');
test(assetRefClone instanceof AssetManager.AssetRef, true, '`assetRefClone` is not type of AssetManager.AssetRef!');
test(assetRefClone.isValid(), true, '`assetRefClone` is not valid!');
test(assetRefClone.manager, assets, '`assetRefClone.manager` is not `assets`!');
test(assetRefClone.id, 'assets/config.json', '`assetRefClone.id` is not the same as resource path!');
test(assetRefClone.data === null, false, '`assetRefClone.data` is not null!');
test(assetRefClone.state, AssetManager.Asset.STATE.READY, '`assetRefClone.state` is not loading!');
test(assetRefClone.assetUnsafe === null, false, '`assetRefClone.assetUnsafe` is null!');
test(assetRefClone.assetUnsafe instanceof TextAsset, true, '`assetRefClone.assetUnsafe` is not type of TextAsset!');
test(assetRefClone.assetUnsafe === assetRef.assetUnsafe, true, '`assetRefClone.assetUnsafe` is not the same as `assetRef.assetUnsafe`!');
test(assetRef.refCount, 2, '`assetRef.refCount` is not equal to 2!');
test(assetRefClone.refCount, 2, '`assetRefClone.refCount` is not equal to 2!');
test(assets.getAssetsIDs().length, 1, '`assets` does not have one asset!');
assetRefClone.destroy();
test(assetRef.refCount, 1, '`assetRef.refCount` is not equal to 1!');
test(assetRefClone.isValid(), false, '`assetRefClone` is valid!');
test(assetRefClone.assetUnsafe, null, '`assetRefClone.assetUnsafe` is not null!');
this.success();
}).step('Release asset acquired from file', function(){
assetRef.destroy();
test(assetRef.isValid(), false, '`assetRef` is valid!');
test(assetRef.assetUnsafe, null, '`assetRef.assetUnsafe` is not null!');
test(assets.getAssetsIDs().length, 0, '`assets` have assets!');
this.success();
}).step('Register asset under ID', function(){
status = assets.registerAsset('config', 'assets/config.json', null, ['text', 'test']);
test(status, true, 'AssetManager.registerAssets() cannot register asset!');
this.success();
}).step('Acquire registered asset from ID', function(){
var self = this;
assetRef = assets.acquire('id://config');
test(assetRef === null, false, '`assetRef` is null!');
test(assetRef instanceof AssetManager.AssetRef, true, '`assetRef` is not type of AssetManager.AssetRef!');
test(assetRef.isValid(), true, '`assetRef` is not valid!');
test(assetRef.manager, assets, '`assetRef.manager` is not `assets`!');
test(assetRef.id, 'config', '`assetRef.id` is not the same as resource path!');
test(assetRef.data, null, '`assetRef.data` is not null!');
test(assetRef.state, AssetManager.Asset.STATE.LOADING, '`assetRef.state` is not loading!');
test(assetRef.assetUnsafe === null, false, '`assetRef.assetUnsafe` is null!');
test(assetRef.assetUnsafe instanceof TextAsset, true, '`assetRef.assetUnsafe` is not type of TextAsset!');
test(assets.getAssetsIDs().length, 1, '`assets` does not have one asset!');
test(assets.getAssetsIDs()[0], 'config', '`assets` does not have asset `config`!');
assetRef.onComplete(function(){
testAsync(assetRef.data === null, false, '`assetRef.data` is null!');
testAsync(typeof assetRef.data, 'string', '`assetRef.data` is not type of object!');
testAsync(assetRef.state, AssetManager.Asset.STATE.READY, '`assetRef.state` is not ready!');
self.success();
});
assetRef.onError(function(){
self.failure('asset cannot be loaded: id://config');
});
}).step('Release asset acquired from ID', function(){
assetRef.destroy();
test(assetRef.isValid(), false, '`assetRef` is valid!');
test(assetRef.assetUnsafe, null, '`assetRef.assetUnsafe` is not null!');
test(assets.getAssetsIDs().length, 0, '`assets` have assets!');
this.success();
}).step('Acquire asset from variants logical expression', function(){
var self = this;
assetRefs = assets.acquire('vars://text & test');
test(Array.isArray(assetRefs), true, '`assetRefs` is not type of Array!');
test(assetRefs.length, 1, '`assetRefs` does not contain one asset!');
assetRef = assetRefs[0];
aseetRefPaths = null;
test(assetRef === null, false, '`assetRef` is null!');
test(assetRef instanceof AssetManager.AssetRef, true, '`assetRef` is not type of AssetManager.AssetRef!');
test(assetRef.isValid(), true, '`assetRef` is not valid!');
test(assetRef.manager, assets, '`assetRef.manager` is not `assets`!');
test(assetRef.id, 'config', '`assetRef.id` is not the same as resource path!');
test(assetRef.data, null, '`assetRef.data` is not null!');
test(assetRef.state, AssetManager.Asset.STATE.LOADING, '`assetRef.state` is not loading!');
test(assetRef.assetUnsafe === null, false, '`assetRef.assetUnsafe` is null!');
test(assetRef.assetUnsafe instanceof TextAsset, true, '`assetRef.assetUnsafe` is not type of TextAsset!');
test(assets.getAssetsIDs().length, 1, '`assets` does not have one asset!');
test(assets.getAssetsIDs()[0], 'config', '`assets` does not have asset `config`!');
assetRef.onComplete(function(){
testAsync(assetRef.data === null, false, '`assetRef.data` is null!');
testAsync(typeof assetRef.data, 'string', '`assetRef.data` is not type of object!');
testAsync(assetRef.state, AssetManager.Asset.STATE.READY, '`assetRef.state` is not ready!');
self.success();
});
assetRef.onError(function(){
self.failure('asset cannot be loaded: id://config');
});
}).step('Release asset acquired from variants logical expression', function(){
assetRef.destroy();
test(assetRef.isValid(), false, '`assetRef` is valid!');
test(assetRef.assetUnsafe, null, '`assetRef.assetUnsafe` is not null!');
test(assets.getAssetsIDs().length, 0, '`assets` have assets!');
this.success();
}).step('Destroy manager', function(){
assets.destroy();
test(assets.getAssetsIDs() === null, true, 'AssetManager.getAssetsIDs() does not returns null!');
test(assets.getAssetsRegistryIDs() === null, true, 'AssetManager.getAssetsRegistryIDs() does not returns null!');
test(assets.getFactoriesRegistryIDs() === null, true, 'AssetManager.getFactoriesRegistryIDs() does not returns null!');
this.success();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment