UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

177 lines (152 loc) 3.65 kB
import Signal from "../../events/signal/Signal.js"; /** * Structure with event signals for observing changes. * Implemented using an Array */ class ArraySet { /** * @readonly */ on = { added: new Signal(), removed: new Signal() }; /** * @private * @type {T[]} */ data = []; length = 0; /** * * @returns {number} */ get size(){ return this.length; } /** * * @param {Array.<T>} [array=[]] * @template T * @constructor * @property {{added: Signal, removed: Signal}} on */ constructor(array) { if (array !== undefined) { this.addAll(array); } } /** * * @param {T} el */ contains(el) { return this.data.indexOf(el) !== -1; } /** * * @param {T} el */ add(el) { if (!this.contains(el)) { this.data.push(el); this.length++; this.on.added.dispatch(el); return true; } else { //element already exists return false; } } /** * * @param {T} el */ remove(el) { const index = this.data.indexOf(el); if (index !== -1) { this.__removeByIndex(index, el); return true; } else { //element not found return false; } } /** * * @param {Number} index * @param {T} el * @private */ __removeByIndex(index, el) { this.data.splice(index, 1); this.length--; this.on.removed.dispatch(el); } /** * * @returns {boolean} */ isEmpty() { return this.length <= 0; } /** * Remove all elements from the set */ clear() { while (!this.isEmpty()) { this.remove(this.data[0]); } } /** * * @param {Array.<T>} elements */ addAll(elements) { const count = elements.length; for (let i = 0; i < count; i++) { this.add(elements[i]); } } /** * Performs a diff on the set and provided collection, elements in the set but not in input are removed and elements in the input but not in the set are added. * @param {Array.<T>} source */ setFromArray(source) { const data = this.data; const sourceCopy = source.slice(); for (let i = data.length - 1; i >= 0; i--) { const element = data[i]; const sourceIndex = sourceCopy.indexOf(element); if (sourceIndex === -1) { //element is in the set currently, but not in the collection which we are trying to copy this.__removeByIndex(i, element); } else { //source element is already in the set sourceCopy.splice(sourceIndex, 1); } } //add the rest to selection for (let i = 0, l = sourceCopy.length; i < l; i++) { this.add(sourceCopy[i]); } } /** * * @param {function(el:T)} visitor * @param {*} [thisArg] */ forEach(visitor, thisArg) { for (let i = 0; i < this.length; i++) { visitor.call(thisArg, this.data[i]); } } /** * * @returns {T[]} */ asArray() { return this.data; } } export default ArraySet;