UNPKG

playcanvas

Version:

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

238 lines (237 loc) 6.32 kB
import { Color } from "../../core/math/color.js"; import { Curve } from "../../core/math/curve.js"; import { CurveSet } from "../../core/math/curve-set.js"; import { Vec2 } from "../../core/math/vec2.js"; import { Vec3 } from "../../core/math/vec3.js"; import { Vec4 } from "../../core/math/vec4.js"; import { GraphNode } from "../../scene/graph-node.js"; import { Asset } from "../asset/asset.js"; const components = ["x", "y", "z", "w"]; const vecLookup = [void 0, void 0, Vec2, Vec3, Vec4]; function rawToValue(app, args, value, old) { switch (args.type) { case "boolean": return !!value; case "number": if (typeof value === "number") { return value; } else if (typeof value === "string") { const v = parseInt(value, 10); if (isNaN(v)) return null; return v; } else if (typeof value === "boolean") { return 0 + value; } return null; case "json": { const result = {}; if (Array.isArray(args.schema)) { if (!value || typeof value !== "object") { value = {}; } for (let i = 0; i < args.schema.length; i++) { const field = args.schema[i]; if (!field.name) continue; if (field.array) { result[field.name] = []; const arr = Array.isArray(value[field.name]) ? value[field.name] : []; for (let j = 0; j < arr.length; j++) { result[field.name].push(rawToValue(app, field, arr[j])); } } else { const val = value.hasOwnProperty(field.name) ? value[field.name] : field.default; result[field.name] = rawToValue(app, field, val); } } } return result; } case "asset": if (value instanceof Asset) { return value; } else if (typeof value === "number") { return app.assets.get(value) || null; } else if (typeof value === "string") { return app.assets.get(parseInt(value, 10)) || null; } return null; case "entity": if (value instanceof GraphNode) { return value; } else if (typeof value === "string") { return app.getEntityFromIndex(value); } return null; case "rgb": case "rgba": if (value instanceof Color) { if (old instanceof Color) { old.copy(value); return old; } return value.clone(); } else if (value instanceof Array && value.length >= 3 && value.length <= 4) { for (let i = 0; i < value.length; i++) { if (typeof value[i] !== "number") { return null; } } if (!old) old = new Color(); old.r = value[0]; old.g = value[1]; old.b = value[2]; old.a = value.length === 3 ? 1 : value[3]; return old; } else if (typeof value === "string" && /#(?:[0-9a-f]{2}){3,4}/i.test(value)) { if (!old) { old = new Color(); } old.fromString(value); return old; } return null; case "vec2": case "vec3": case "vec4": { const len = parseInt(args.type.slice(3), 10); const vecType = vecLookup[len]; if (value instanceof vecType) { if (old instanceof vecType) { old.copy(value); return old; } return value.clone(); } else if (value instanceof Array && value.length === len) { for (let i = 0; i < value.length; i++) { if (typeof value[i] !== "number") { return null; } } if (!old) old = new vecType(); for (let i = 0; i < len; i++) { old[components[i]] = value[i]; } return old; } return null; } case "curve": if (value) { let curve; if (value instanceof Curve || value instanceof CurveSet) { curve = value.clone(); } else { const CurveType = value.keys[0] instanceof Array ? CurveSet : Curve; curve = new CurveType(value.keys); curve.type = value.type; } return curve; } break; } return value; } function attributeToValue(app, schema, value, current) { if (schema.array) { return value.map((item, index) => rawToValue(app, schema, item, current ? current[index] : null)); } return rawToValue(app, schema, value, current); } function assignAttributesToScript(app, attributeSchemaMap, data, script) { if (!data) return; for (const attributeName in attributeSchemaMap) { const attributeSchema = attributeSchemaMap[attributeName]; const dataToAssign = data[attributeName]; if (dataToAssign === void 0) continue; script[attributeName] = attributeToValue(app, attributeSchema, dataToAssign, script[attributeName]); } } class ScriptAttributes { static assignAttributesToScript = assignAttributesToScript; static attributeToValue = attributeToValue; constructor(scriptType) { this.scriptType = scriptType; this.index = {}; } static reservedNames = /* @__PURE__ */ new Set([ "app", "entity", "enabled", "_enabled", "_enabledOld", "_destroyed", "__attributes", "__attributesRaw", "__scriptType", "__executionOrder", "_callbacks", "_callbackActive", "has", "get", "on", "off", "fire", "once", "hasEvent" ]); add(name, args) { if (!args) { return; } if (!args.type) { return; } if (this.index[name]) { return; } else if (ScriptAttributes.reservedNames.has(name)) { return; } this.index[name] = args; Object.defineProperty(this.scriptType.prototype, name, { get: function() { return this.__attributes[name]; }, set: function(raw) { const evt = "attr"; const evtName = `attr:${name}`; const old = this.__attributes[name]; let oldCopy = old; if (old && args.type !== "json" && args.type !== "entity" && old.clone) { if (this.hasEvent(evt) || this.hasEvent(evtName)) { oldCopy = old.clone(); } } if (args.array) { this.__attributes[name] = []; if (raw) { for (let i = 0, len = raw.length; i < len; i++) { this.__attributes[name].push(rawToValue(this.app, args, raw[i], old ? old[i] : null)); } } } else { this.__attributes[name] = rawToValue(this.app, args, raw, old); } this.fire(evt, name, this.__attributes[name], oldCopy); this.fire(evtName, this.__attributes[name], oldCopy); } }); } remove(name) { if (!this.index[name]) { return false; } delete this.index[name]; delete this.scriptType.prototype[name]; return true; } has(name) { return !!this.index[name]; } get(name) { return this.index[name] || null; } } export { ScriptAttributes, assignAttributesToScript };