import { Utils } from '../common/Utils';
import { EventType } from '../const';
import { ActionManager } from '../managers/ActionManager';
import { Selector } from './Selector';
const _createEventTagName = '__DynamicSelector__createEventTagName';
const _destroyEventTagName = '__DynamicSelector__destroyEventTagName';
/**
* @class DynamicSelector
* The dynamic selector to find objects with some conditions.
* @memberof THING
*/
class DynamicSelector extends Selector {
constructor(parent, condition, param = {}) {
super(param);
this._parent = parent;
this._condition = condition;
this._callbacks = {
onAdd: Utils.parseValue(param.onAdd, null),
onRemove: Utils.parseValue(param.onRemove, null),
};
this._registerEvents();
this.messages = [];
}
/**
* dispose
* @public
*/
dispose() {
this._unregisterEvents();
super.clear();
}
run(message, options = {}) {
// Process the action.
this._processActionByMessage(message, this.objects);
// When needs auto merge the same message,delete the old same message.
let autoMerge = options.autoMerge || true;
if (autoMerge) {
this.messages = this.messages.filter(msg => {
return msg.type != message.type;
});
}
// Save the message.
this.messages.push(message);
}
// #region Private
_check(object) {
return object.queryable && object.test(this._condition);
}
_registerEvents() {
this._parent.on(EventType.Create, '*', (ev) => {
let object = ev.object;
if (!this._check(object)) {
return;
}
this._onCreateObject(object);
}, _createEventTagName);
this._parent.on(EventType.BeforeDestroy, '*', (ev) => {
let object = ev.object;
if (!this._check(object)) {
return;
}
this._onDestroyObject(object);
}, _destroyEventTagName);
}
_unregisterEvents() {
this._parent.off(EventType.Create, '*', _createEventTagName);
this._parent.off(EventType.BeforeDestroy, '*', _destroyEventTagName);
}
_onCreateObject(object) {
let objects = this._objects;
let index = objects.indexOf(object);
if (index !== -1) {
return;
}
objects.push(object);
let onAdd = this._callbacks['onAdd'];
if (onAdd) {
onAdd(object);
}
// Let all objects run these actions.
this.messages.forEach((msg) => {
this._processActionByMessage(msg, [object]);
})
}
_processActionByMessage(message, objects) {
// Get the action by message type.
let { type, params } = message;
let action = Utils.getCurrentApp().actionManager.getActionByName(type);
if (!action) {
return;
}
// Process the action.
ActionManager.processAction(action, objects, null, params);
}
_onDestroyObject(object) {
let objects = this._objects;
let index = objects.indexOf(object);
if (index === -1) {
return;
}
objects.splice(index, 1);
let onRemove = this._callbacks['onRemove'];
if (onRemove) {
onRemove(object);
}
}
// #endregion
onCreateInstance() {
return new DynamicSelector(this._parent, this._condition, arguments[0]);
}
get callbacks() {
return this._callbacks;
}
/**
* Check class type.
* @type {Boolean}
* @example
* let object = new THING.Object3D();
* let selector = new THING.DynamicSelector(object, '*');
* // @expect(selector.isDynamicSelector == true);
*/
get isDynamicSelector() {
return true;
}
}
export { DynamicSelector };