import { Utils } from '../common/Utils';
const __ = {
private: Symbol('private'),
}
/**
* @class ObjectManager
* The object manager.
* @memberof THING
*/
class ObjectManager {
/**
* The object manager to manage object(s) life.
*/
constructor() {
this[__.private] = {};
let _private = this[__.private];
_private.objects = [];
_private.objectIdMaps = new Map();
_private.objectUUIDMaps = new Map();
_private.tickableObjects = [];
_private.resizableObjects = [];
_private.dirtyObjects = [];
_private.lateUpdateObjects = [];
_private.keepAliveObjects = [];
if (_DEBUG) {
_private.gcObjects = new Set();
_private.app = Utils.getCurrentApp();
_private.onGCDestroyObjectCallback = (key) => {
_private.gcObjects.delete(key);
};
_private.app.global.gc.registerDestroyObjectCallback(_private.onGCDestroyObjectCallback);
}
}
// #region Private
_buildObjectGCKey(object) {
let { type, name, id, uuid } = object;
return `type: '${type}', name: '${name}', id: '${id}', uuid: '${uuid}'`;
}
// #endregion
dispose() {
let _private = this[__.private];
_private.objects = [];
_private.objectIdMaps.clear();
_private.objectUUIDMaps.clear();
_private.tickableObjects = [];
_private.resizableObjects = [];
_private.dirtyObjects = [];
_private.lateUpdateObjects = [];
_private.keepAliveObjects = [];
if (_DEBUG) {
_private.app.global.gc.unregisterDestroyObjectCallback(_private.onGCDestroyObjectCallback);
_private.app = null;
}
}
resize(width, height) {
let _private = this[__.private];
let resizableObjects = _private.resizableObjects;
for (let i = 0, l = resizableObjects.length; i < l; i++) {
resizableObjects[i].onResize(width, height);
}
}
update(deltaTime) {
let _private = this[__.private];
// Update dirty objects
let dirtyObjects = _private.dirtyObjects;
if (dirtyObjects.length) {
for (let i = 0, l = dirtyObjects.length; i < l; i++) {
dirtyObjects[i].onRefresh();
}
dirtyObjects.length = 0;
}
// Update tickable objects
let tickableObjects = _private.tickableObjects;
for (let i = 0, l = tickableObjects.length; i < l; i++) {
let object = tickableObjects[i];
if (object.isWaitingForUpdate) {
continue;
}
object.onUpdate(deltaTime);
}
}
lateUpdate(deltaTime) {
let _private = this[__.private];
let objects = _private.lateUpdateObjects;
for (let i = 0, l = objects.length; i < l; i++) {
objects[i].onLateUpdate(deltaTime);
}
}
getBaseObjectFromOrderID(orderId) {
let _private = this[__.private];
return _private.objectIdMaps.get(orderId);
}
getBaseObjectFromUUID(uuid) {
let _private = this[__.private];
return _private.objectUUIDMaps.get(uuid);
}
getBaseObjectFromNode(node) {
let _private = this[__.private];
let rootNode = node;
while (rootNode) {
let userData = rootNode.getUserData();
let orderId = userData['baseObject_orderID'];
if (orderId) {
return _private.objectIdMaps.get(orderId);
}
rootNode = rootNode.getParent();
}
return null;
}
addObject(object) {
let _private = this[__.private];
_private.objectIdMaps.set(object.orderId, object);
_private.objectUUIDMaps.set(object.uuid, object);
_private.objects.push(object);
// Watch GC to check memory leak
if (_DEBUG) {
let key = this._buildObjectGCKey(object);
_private.gcObjects.add(key);
_private.app.global.gc.register(object, key);
}
}
removeObject(object) {
let _private = this[__.private];
_private.objectIdMaps.delete(object.orderId);
_private.objectUUIDMaps.delete(object.uuid);
Utils.removeFromArray(_private.objects, object);
Utils.removeFromArray(_private.tickableObjects, object);
Utils.removeFromArray(_private.resizableObjects, object);
}
addDirtyObject(object) {
let _private = this[__.private];
_private.dirtyObjects.push(object);
}
removeDirtyObject(object) {
let _private = this[__.private];
Utils.removeFromArray(_private.dirtyObjects, object);
}
addTickableObject(object) {
let _private = this[__.private];
_private.tickableObjects.push(object);
}
insertTickableObject(index, object) {
let _private = this[__.private];
_private.tickableObjects._insert(index, object);
}
removeTickableObject(object) {
let _private = this[__.private];
Utils.removeFromArray(_private.tickableObjects, object);
}
addResizableObject(object) {
let _private = this[__.private];
_private.resizableObjects.push(object);
}
removeResizableObject(object) {
let _private = this[__.private];
Utils.removeFromArray(_private.resizableObjects, object);
}
addLateUpdateObject(object) {
let _private = this[__.private];
_private.lateUpdateObjects.push(object);
}
removeLateUpdateObject(object) {
let _private = this[__.private];
Utils.removeFromArray(_private.lateUpdateObjects, object);
}
addKeepAliveObject(object) {
let _private = this[__.private];
_private.keepAliveObjects.push(object);
}
removeKeepAliveObject(object) {
let _private = this[__.private];
Utils.removeFromArray(_private.keepAliveObjects, object);
}
clearKeepAliveObjects() {
let _private = this[__.private];
_private.keepAliveObjects.length = 0;
}
get gc() {
if (_DEBUG) {
let _private = this[__.private];
return {
objects: _private.gcObjects
};
}
else {
return null;
}
}
get objects() {
let _private = this[__.private];
return _private.objects;
}
get tickableObjects() {
let _private = this[__.private];
return _private.tickableObjects;
}
get lateUpdateObjects() {
let _private = this[__.private];
return _private.lateUpdateObjects;
}
get resizableObjects() {
let _private = this[__.private];
return _private.resizableObjects;
}
get dirtyObjects() {
let _private = this[__.private];
return _private.dirtyObjects;
}
get keepAliveObjects() {
let _private = this[__.private];
return _private.keepAliveObjects;
}
}
export { ObjectManager }