UNPKG

@awayjs/core

Version:
154 lines (122 loc) 4.05 kB
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; } }