@javelin/ecs
Version:
161 lines • 5.19 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSchemaId = exports.toComponent = exports.toComponentFromType = exports.component = exports.registerSchema = exports.createComponentPool = exports.isComponentOf = exports.$pool = exports.$type = void 0;
const core_1 = require("@javelin/core");
const internal_1 = require("./internal");
exports.$type = Symbol("javelin_component_type");
exports.$pool = Symbol("javelin_component_pool");
const { schemaIndex, schemaPools, instanceTypeLookup } = internal_1.UNSAFE_internals;
let schemaIds = 0;
function createComponentBase(schema, pool = true) {
return Object.defineProperties({}, {
[exports.$type]: {
value: schemaIndex.get(schema),
writable: false,
enumerable: false,
},
[exports.$pool]: {
value: pool,
writable: false,
enumerable: false,
},
});
}
/**
* Check if a component is an instance of a component type.
* @param component
* @param schema
* @returns
* @example
* const A = {}
* const B = {}
* const a = component(A)
* isComponentOf(a, A) // true
* isComponentOf(a, B) // false
*/
function isComponentOf(component, schema) {
return getSchemaId(component) === schemaIndex.get(schema);
}
exports.isComponentOf = isComponentOf;
function createComponentPool(schema, poolSize) {
const componentPool = core_1.createStackPool(() => core_1.createSchemaInstance(schema, createComponentBase(schema)), component => core_1.resetSchemaInstance(component, schema), poolSize);
return componentPool;
}
exports.createComponentPool = createComponentPool;
const modelConfig = new Map();
/**
* Manually register a component type. Optionally specify a unique, integer id
* and/or size for the component type's object pool.
* @param schema
* @param schemaId
* @param [poolSize=1000]
* @returns
* @example <caption>register a schema as a component type (optional)</caption>
* ```ts
* const Vehicle = { torque: number }
* registerSchema(Vehicle)
* ```
* @example <caption>register a schema with a fixed id</caption>
* ```ts
* const Vehicle = { torque: number }
* registerSchema(Vehicle, 22)
* ```
* @example <caption>register a schema with a fixed id and pool size</caption>
* ```ts
* const Particle = { color: number }
* registerSchema(Particle, 3, 10_000)
* ```
*/
function registerSchema(schema, schemaId, poolSize = 1000) {
let type = schemaIndex.get(schema);
if (type !== undefined) {
return type;
}
type = schemaId;
if (type === undefined) {
while (modelConfig.has(schemaIds)) {
schemaIds++;
}
type = schemaIds;
}
else if (modelConfig.has(type)) {
throw new Error("Failed to register component type: a component with same id is already registered");
}
if (poolSize > 0) {
schemaPools.set(type, createComponentPool(schema, poolSize));
}
modelConfig.set(type, schema);
schemaIndex.set(schema, type);
internal_1.UNSAFE_setModel(core_1.createModel(modelConfig));
return type;
}
exports.registerSchema = registerSchema;
function createComponentInner(schema) {
const type = registerSchema(schema);
const pool = internal_1.UNSAFE_internals.schemaPools.get(type);
return (pool
? pool.retain()
: core_1.createSchemaInstance(schema, createComponentBase(schema, false)));
}
/**
* Use a Schema to create a component. The second parameter is an optional
* object that will be used to assign initial values to the new component
* instance.
* @param schema
* @param props
* @returns
* @example
* ```ts
* const Quaternion = { x: number, y: number, z: number, w: number }
* const quaternion = component(Quaternion, { w: 1 })
* ```
*/
function component(schema, props) {
const instance = createComponentInner(schema);
if (props !== undefined) {
Object.assign(instance, props);
}
return instance;
}
exports.component = component;
function toComponentFromType(object, type) {
try {
;
object[exports.$type] = type;
object[exports.$pool] = false;
}
catch { }
if (object[exports.$type] !== type) {
instanceTypeLookup.set(object, type);
}
return object;
}
exports.toComponentFromType = toComponentFromType;
/**
* Instruct the ECS to treat an object as a component instance of a given
* schema.
* @param object
* @param schema
* @returns
*/
function toComponent(object, schema) {
const type = registerSchema(schema, undefined, 0);
return toComponentFromType(object, type);
}
exports.toComponent = toComponent;
/**
* Get the type id (number) of a component. Throws an error if the object is
* not a valid component.
* @param component
* @returns
*/
function getSchemaId(component) {
var _a;
const type = (_a = component[exports.$type]) !== null && _a !== void 0 ? _a : instanceTypeLookup.get(component);
if (type === undefined) {
throw new Error("Failed to get component type id: object is not a component");
}
return type;
}
exports.getSchemaId = getSchemaId;
//# sourceMappingURL=component.js.map