UNPKG

@thi.ng/ecs

Version:

Entity Component System based around typed arrays & sparse sets

94 lines (93 loc) 2.48 kB
import { typedArray } from "@thi.ng/api/typedarray"; import { assert } from "@thi.ng/errors/assert"; import { AComponent } from "./acomponent.js"; class MemMappedComponent extends AComponent { type; size; stride; cache; constructor(sparse, dense, opts) { opts = { size: 1, byteOffset: 0, ...opts }; const size = opts.size; const stride = opts.stride || size; super( opts.id, sparse, dense, opts.buf ? typedArray( opts.type, opts.buf, opts.byteOffset, dense.length * stride ) : typedArray(opts.type, dense.length * stride) ); this.type = opts.type; this.size = size; this.stride = stride; this.default = opts.default; this.cache = opts.cache; } packedValues() { return this.vals.subarray(0, this.n * this.stride); } resize(pool, cap) { assert(cap >= this.dense.length, "can't decrease capacity"); if (cap === this.dense.length) return; const sparse = pool.reallocArray(this.sparse, cap); const dense = pool.reallocArray(this.dense, cap); const vals = pool.reallocArray(this.vals, cap * this.stride); assert( !!(sparse && dense && vals), `couldn't resize component: ${this.id}` ); this.sparse = sparse; this.dense = dense; this.vals = vals; this.cache?.clear(); } get(id) { let i = this.sparse[id]; return this.dense[i] === id ? this.getIndex(i) : void 0; } getIndex(i) { return i < this.n ? this.cache ? this.cache.getSet(i, () => { i *= this.stride; return this.vals.subarray(i, i + this.size); }) : (i *= this.stride, this.vals.subarray(i, i + this.size)) : void 0; } setIndexUnsafe(i, val, notify = true) { this.vals.set(val, i * this.stride); notify && this.notifyChange(this.dense[i]); } swapIndices(src, dest) { if (src === dest) return false; const { dense, sparse, vals, size, stride } = this; const ss = dense[src]; const sd = dense[dest]; dense[src] = sd; dense[dest] = ss; sparse[ss] = dest; sparse[sd] = src; src *= stride; dest *= stride; const tmp = vals.slice(src, src + size); vals.copyWithin(src, dest, dest + size); vals.set(tmp, dest); return true; } moveIndex(src, dest) { const s = this.stride; src *= s; this.vals.copyWithin(dest * s, src, src + this.size); this.cache?.delete(dest); } } export { MemMappedComponent };