UNPKG

ecsy

Version:
238 lines (193 loc) 7.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Not = Not; exports.System = void 0; var _Query = _interopRequireDefault(require("./Query.js")); var _Utils = require("./Utils.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class System { canExecute() { if (this._mandatoryQueries.length === 0) return true; for (let i = 0; i < this._mandatoryQueries.length; i++) { var query = this._mandatoryQueries[i]; if (query.entities.length === 0) { return false; } } return true; } getName() { return this.constructor.getName(); } constructor(world, attributes) { this.world = world; this.enabled = true; // @todo Better naming :) this._queries = {}; this.queries = {}; this.priority = 0; // Used for stats this.executeTime = 0; if (attributes && attributes.priority) { this.priority = attributes.priority; } this._mandatoryQueries = []; this.initialized = true; if (this.constructor.queries) { for (var queryName in this.constructor.queries) { var queryConfig = this.constructor.queries[queryName]; var Components = queryConfig.components; if (!Components || Components.length === 0) { throw new Error("'components' attribute can't be empty in a query"); } // Detect if the components have already been registered let unregisteredComponents = Components.filter(Component => !(0, _Utils.componentRegistered)(Component)); if (unregisteredComponents.length > 0) { throw new Error(`Tried to create a query '${this.constructor.name}.${queryName}' with unregistered components: [${unregisteredComponents.map(c => c.getName()).join(", ")}]`); } var query = this.world.entityManager.queryComponents(Components); this._queries[queryName] = query; if (queryConfig.mandatory === true) { this._mandatoryQueries.push(query); } this.queries[queryName] = { results: query.entities }; // Reactive configuration added/removed/changed var validEvents = ["added", "removed", "changed"]; const eventMapping = { added: _Query.default.prototype.ENTITY_ADDED, removed: _Query.default.prototype.ENTITY_REMOVED, changed: _Query.default.prototype.COMPONENT_CHANGED // Query.prototype.ENTITY_CHANGED }; if (queryConfig.listen) { validEvents.forEach(eventName => { if (!this.execute) { console.warn(`System '${this.getName()}' has defined listen events (${validEvents.join(", ")}) for query '${queryName}' but it does not implement the 'execute' method.`); } // Is the event enabled on this system's query? if (queryConfig.listen[eventName]) { let event = queryConfig.listen[eventName]; if (eventName === "changed") { query.reactive = true; if (event === true) { // Any change on the entity from the components in the query let eventList = this.queries[queryName][eventName] = []; query.eventDispatcher.addEventListener(_Query.default.prototype.COMPONENT_CHANGED, entity => { // Avoid duplicates if (eventList.indexOf(entity) === -1) { eventList.push(entity); } }); } else if (Array.isArray(event)) { let eventList = this.queries[queryName][eventName] = []; query.eventDispatcher.addEventListener(_Query.default.prototype.COMPONENT_CHANGED, (entity, changedComponent) => { // Avoid duplicates if (event.indexOf(changedComponent.constructor) !== -1 && eventList.indexOf(entity) === -1) { eventList.push(entity); } }); } else { /* // Checking just specific components let changedList = (this.queries[queryName][eventName] = {}); event.forEach(component => { let eventList = (changedList[ componentPropertyName(component) ] = []); query.eventDispatcher.addEventListener( Query.prototype.COMPONENT_CHANGED, (entity, changedComponent) => { if ( changedComponent.constructor === component && eventList.indexOf(entity) === -1 ) { eventList.push(entity); } } ); }); */ } } else { let eventList = this.queries[queryName][eventName] = []; query.eventDispatcher.addEventListener(eventMapping[eventName], entity => { // @fixme overhead? if (eventList.indexOf(entity) === -1) eventList.push(entity); }); } } }); } } } } stop() { this.executeTime = 0; this.enabled = false; } play() { this.enabled = true; } // @question rename to clear queues? clearEvents() { for (let queryName in this.queries) { var query = this.queries[queryName]; if (query.added) { query.added.length = 0; } if (query.removed) { query.removed.length = 0; } if (query.changed) { if (Array.isArray(query.changed)) { query.changed.length = 0; } else { for (let name in query.changed) { query.changed[name].length = 0; } } } } } toJSON() { var json = { name: this.getName(), enabled: this.enabled, executeTime: this.executeTime, priority: this.priority, queries: {} }; if (this.constructor.queries) { var queries = this.constructor.queries; for (let queryName in queries) { let query = this.queries[queryName]; let queryDefinition = queries[queryName]; let jsonQuery = json.queries[queryName] = { key: this._queries[queryName].key }; jsonQuery.mandatory = queryDefinition.mandatory === true; jsonQuery.reactive = queryDefinition.listen && (queryDefinition.listen.added === true || queryDefinition.listen.removed === true || queryDefinition.listen.changed === true || Array.isArray(queryDefinition.listen.changed)); if (jsonQuery.reactive) { jsonQuery.listen = {}; const methods = ["added", "removed", "changed"]; methods.forEach(method => { if (query[method]) { jsonQuery.listen[method] = { entities: query[method].length }; } }); } } } return json; } } exports.System = System; System.isSystem = true; System.getName = function () { return this.displayName || this.name; }; function Not(Component) { return { operator: "not", Component: Component }; }