@thi.ng/ecs
Version:
Entity Component System based around typed arrays & sparse sets
94 lines (93 loc) • 2.48 kB
JavaScript
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
};