import { Flags } from '@uino/base-thing';
import { BaseComponent } from './BaseComponent';
import { EventType } from '../const';
const Flag = {
Enable: 1 << 0,
AutoRelease: 1 << 1,
}
const cDynamicLoadComponentTagName = '__cDynamicLoadComponentTagName__';
/**
* @class DynamicLoadComponent
* The dynamic load component.
* @memberof THING
* @extends THING.BaseComponent
*/
class DynamicLoadComponent extends BaseComponent {
static mustCopyWithInstance = true;
_flags = new Flags();
_aliveTime = 60 * 1000; // Milliseconds
_pendingUnloadObjects = new Map();
/**
* Load or unload object's resources when show or hide it automaticly.
*/
constructor() {
super();
}
// #region Private Functions
_loadResource(object) {
let pendingUnloadObjects = this._pendingUnloadObjects;
if (object.active && object.visible) {
if (!object.loading) {
object.loadResource(false);
}
pendingUnloadObjects.delete(object);
}
else if (object.loaded) {
let pendingUnloadObject = pendingUnloadObjects.get(object);
if (!pendingUnloadObject) {
pendingUnloadObjects.set(object, { aliveTime: this._aliveTime });
}
}
}
// #endregion
// #region BaseComponent
onAdd(object) {
super.onAdd(object);
this.enable = true;
}
onRemove() {
this.enable = false;
this.autoRelease = false;
this._pendingUnloadObjects.clear();
super.onRemove();
}
// #endregion
/**
* Enable/Disable dynamic load.
* @type {Boolean}
* @private
*/
get enable() {
return this._flags.has(Flag.Enable);
}
set enable(value) {
if (this._flags.enable(Flag.Enable, value)) {
if (value) {
let pendingUnloadObjects = this._pendingUnloadObjects;
// Destroy
this.object.on(EventType.AfterDestroy, '.Object3D', (ev) => {
let object = ev.object;
pendingUnloadObjects.delete(object);
}, cDynamicLoadComponentTagName);
// Load/Unload resource when visible change
this.object.on(EventType.VisibleChange, '.Object3D', (ev) => {
this._loadResource(ev.object);
}, cDynamicLoadComponentTagName);
}
else {
this.object.off(EventType.AfterDestroy, cDynamicLoadComponentTagName);
this.object.off(EventType.VisibleChange, cDynamicLoadComponentTagName);
}
}
}
/**
* Get/Set alive time in milliseconds.
* @type {Number}
* @private
*/
get aliveTime() {
return this._aliveTime;
}
set aliveTime(value) {
this._aliveTime = value;
}
/**
* Enable/Disable auto release resources.
* @type {Boolean}
* @private
*/
get autoRelease() {
return this._flags.has(Flag.AutoRelease);
}
set autoRelease(value) {
if (this._flags.enable(Flag.AutoRelease, value)) {
if (value) {
this.object.app.on(EventType.Update, (ev) => {
// Conver seconds to milliseconds
let deltaTime = ev.deltaTime * 1000;
// Try to unload objects resource by alive time
let pendingUnloadObjects = this._pendingUnloadObjects;
pendingUnloadObjects.forEach((pendingUnloadObject, object) => {
if (pendingUnloadObject.aliveTime >= deltaTime) {
pendingUnloadObject.aliveTime -= deltaTime;
}
else {
object.unloadResource(false);
pendingUnloadObjects.delete(object);
}
});
}, cDynamicLoadComponentTagName);
}
else {
this.object.app.off(EventType.Update, cDynamicLoadComponentTagName);
}
}
}
}
export { DynamicLoadComponent }