UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

125 lines (124 loc) 3.21 kB
import { EventHandler } from "../../core/event-handler.js"; import { Color } from "../../core/math/color.js"; import { Vec2 } from "../../core/math/vec2.js"; import { Vec3 } from "../../core/math/vec3.js"; import { Vec4 } from "../../core/math/vec4.js"; class ComponentSystem extends EventHandler { id; constructor(app) { super(); this.app = app; this.store = {}; this.schema = []; } addComponent(entity, data = {}) { const component = new this.ComponentType(this, entity); const componentData = new this.DataType(); this.store[entity.guid] = { entity, data: componentData }; entity[this.id] = component; entity.c[this.id] = component; this.initializeComponentData(component, data, []); this.fire("add", entity, component); return component; } removeComponent(entity) { const id = this.id; const record = this.store[entity.guid]; const component = entity.c[id]; component.fire("beforeremove"); this.fire("beforeremove", entity, component); delete this.store[entity.guid]; entity[id] = void 0; delete entity.c[id]; this.fire("remove", entity, record.data); } cloneComponent(entity, clone) { const src = this.store[entity.guid]; return this.addComponent(clone, src.data); } initializeComponentData(component, data = {}, properties) { for (let i = 0, len = properties.length; i < len; i++) { const descriptor = properties[i]; let name, type; if (typeof descriptor === "object") { name = descriptor.name; type = descriptor.type; } else { name = descriptor; type = void 0; } let value = data[name]; if (value !== void 0) { if (type !== void 0) { value = convertValue(value, type); } component[name] = value; } else { component[name] = component.data[name]; } } if (component.enabled && component.entity.enabled) { component.onEnable(); } } getPropertiesOfType(type) { const matchingProperties = []; const schema = this.schema || []; schema.forEach((descriptor) => { if (descriptor && typeof descriptor === "object" && descriptor.type === type) { matchingProperties.push(descriptor); } }); return matchingProperties; } destroy() { this.off(); } } function convertValue(value, type) { if (!value) { return value; } switch (type) { case "rgb": if (value instanceof Color) { return value.clone(); } return new Color(value[0], value[1], value[2]); case "rgba": if (value instanceof Color) { return value.clone(); } return new Color(value[0], value[1], value[2], value[3]); case "vec2": if (value instanceof Vec2) { return value.clone(); } return new Vec2(value[0], value[1]); case "vec3": if (value instanceof Vec3) { return value.clone(); } return new Vec3(value[0], value[1], value[2]); case "vec4": if (value instanceof Vec4) { return value.clone(); } return new Vec4(value[0], value[1], value[2], value[3]); case "boolean": case "number": case "string": return value; case "entity": return value; // Entity fields should just be a string guid default: throw new Error(`Could not convert unhandled type: ${type}`); } } export { ComponentSystem };