@awayjs/core
Version:
AwayJS core classes
154 lines (122 loc) • 4.05 kB
text/typescript
import { AbstractMethodError } from '../errors/AbstractMethodError';
import { AssetEvent } from '../events/AssetEvent';
import { EventDispatcher } from '../events/EventDispatcher';
import { AbstractionBase } from './AbstractionBase';
import { IAbstraction } from './IAbstraction';
import { IAbstractionPool } from './IAbstractionPool';
import { IAsset } from './IAsset';
import { IAssetAdapter } from './IAssetAdapter';
import { IAssetClass } from './IAssetClass';
import { UUID } from './UUID';
export class AssetBase extends EventDispatcher implements IAsset, IAssetAdapter {
private __finalizer: FinalizationRegistry<number>;
public _symbol: any;
public _adapter: IAssetAdapter;
private _namespace: string;
private _name: string;
protected _abstractionPool: Record<number, IAbstraction> = {};
public static DEFAULT_NAMESPACE: string = 'default';
public get finalizer(): FinalizationRegistry<number> {
return this.__finalizer || (this.__finalizer = new FinalizationRegistry((poolId: number) => {
const abstraction = this._abstractionPool[poolId];
if (abstraction) { // check abstraction hasn't already been cleared
console.debug('[' + abstraction.constructor.name + '] abstraction was deleted by GC:', poolId);
abstraction.onClear(null);
}
}));
}
/**
* A unique id for the asset, used to identify assets in an associative array
*/
public readonly id: number;
constructor() {
super();
this.id = UUID.Next();
}
public get adaptee(): AssetBase {
return this;
}
/**
* adapter is used to provide MovieClip to scripts taken from different platforms
* setter typically managed by factory. getter defaults to AwayJS class
*/
public get adapter(): IAssetAdapter {
return this._adapter || this;
}
public set adapter(value: IAssetAdapter) {
this._adapter = value;
}
/**
*
*/
public get assetType(): string {
throw new AbstractMethodError();
}
public get name(): string {
return this._name;
}
public set name(val: string) {
const prev = this._name;
this._name = val;
if (this._name == null)
this._name = 'null';
this.dispatchEvent(new AssetEvent(AssetEvent.RENAME, this, prev));
}
/**
*
*/
public invalidate(): void {
for (const key in this._abstractionPool)
this._abstractionPool[key].onInvalidate(null);
}
/**
* @inheritDoc
*/
public dispose(): void {
throw new AbstractMethodError();
}
public clone(): AssetBase {
throw new AbstractMethodError();
}
public clear(): void {
for (const key in this._abstractionPool)
this._abstractionPool[key].onClear(null);
}
public get assetNamespace(): string {
return this._namespace;
}
public set assetNamespace(value: string) {
this._namespace = value ? value : AssetBase.DEFAULT_NAMESPACE;
}
public assetPathEquals(name: string, ns: string): boolean {
return (this._name == name && (!ns || this._namespace == ns));
}
public isAsset(assetClass: IAssetClass): boolean {
return this.assetType == assetClass.assetType;
}
public resetAssetPath(name: string, ns: string = null): void {
this._name = name ? name : 'null';
this._namespace = ns ? ns : AssetBase.DEFAULT_NAMESPACE;
}
public getAbstraction <T extends AbstractionBase>(pool: IAbstractionPool): T {
return <T> this._abstractionPool[pool.id]
|| <T> (this._abstractionPool[pool.id] = this.getNewAbstraction(pool));
}
public checkAbstraction <T extends AbstractionBase>(pool: IAbstractionPool): T {
return <T> this._abstractionPool[pool.id];
}
public clearAbstraction(pool: IAbstractionPool | number) {
// in cases where pool has been GC'd, we still need to remove abstraction from _abstractionPool
if (typeof pool == 'number') {
delete this._abstractionPool[pool];
return;
}
pool.storeAbstraction(this._abstractionPool[pool.id]);
delete this._abstractionPool[pool.id];
}
public getNewAbstraction(pool: IAbstractionPool): IAbstraction {
const abstraction: IAbstraction = pool.requestAbstraction(this);
abstraction.init(this, pool);
return abstraction;
}
}