UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

543 lines (542 loc) 16.6 kB
"use strict"; import { Color, Vector2, Vector3, Vector4 } from "three"; import { Attribute, CoreAttribute } from "../../Attribute"; import { AttribType, AttribClass } from "../../Constant"; import { CoreEntityWithObject } from "../../CoreEntity"; import { isArray, isVector, isColor, isString } from "../../../Type"; import { EntityGroupCollection } from "../../EntityGroupCollection"; import { _updateObjectAttribRef } from "../../../reactivity/ObjectAttributeReactivityUpdateRef"; import { attribValueNonPrimitive, copyAttribValue, cloneAttribValue, uniqRelatedEntityIds } from "../utils/Common"; import { getOrCreateObjectAttributeRef } from "../../../reactivity/ObjectAttributeReactivityCreateRef"; import { watch } from "../../../reactivity/CoreReactivity"; import { objectData } from "./BaseCoreObjectUtils"; import { TypeAssert } from "../../../../engine/poly/Assert"; var PropertyName = /* @__PURE__ */ ((PropertyName2) => { PropertyName2["NAME"] = "name"; PropertyName2["POSITION"] = "position"; return PropertyName2; })(PropertyName || {}); const ATTRIBUTES = "attributes"; const ORIGIN = new Vector3(0, 0, 0); function _convertArrayToVector(value) { switch (value.length) { case 1: return value[0]; case 2: return new Vector2(value[0], value[1]); case 3: return new Vector3(value[0], value[1], value[2]); case 4: return new Vector4(value[0], value[1], value[2], value[3]); } } const tmpVec3 = new Vector3(); const tmpN3 = [0, 0, 0]; const _relatedPrimitiveIds = []; const _relatedVertexIds = []; export class BaseCoreObject extends CoreEntityWithObject { dispose() { } // set_index(i: number) { // this._index = i; // } geometry() { var _a; return ((_a = this._object) == null ? void 0 : _a.geometry) || null; } builder() { return void 0; } static attributeRef(object, attribName, type, defaultValue) { return getOrCreateObjectAttributeRef(object, attribName, type, defaultValue); } attributeRef(attribName, type, defaultValue) { if (!this._object) { return; } return this.constructor.attributeRef( this._object, attribName, type, defaultValue ); } static onAttribChange(object, attribName, type, defaultValue, callback) { const ref = this.attributeRef(object, attribName, type, defaultValue); return watch(ref.current, callback); } onAttribChange(attribName, type, defaultValue, callback) { if (!this._object) { return; } return this.constructor.onAttribChange( this._object, attribName, type, defaultValue, callback ); } static setAttribute(object, attribName, value) { this.addAttribute(object, attribName, value); } static addAttribute(object, attribName, value) { if (isArray(value)) { const convertedValue = _convertArrayToVector(value); if (!convertedValue) { const message = `value invalid`; console.error(message, value); throw new Error(message); } } const dict = this._attributesDictionary(object); const currentValue = dict[attribName]; if (attribValueNonPrimitive(value)) { if (currentValue == null) { const cloned = cloneAttribValue(value); if (cloned) { dict[attribName] = cloned; } } else { if (attribValueNonPrimitive(currentValue)) { copyAttribValue(value, currentValue); } } } else { dict[attribName] = value; } _updateObjectAttribRef(object, attribName, value); } static addNumericAttribute(object, attribName, size = 1, defaultValue = 0) { this.addAttribute(object, attribName, defaultValue); } addAttribute(name, value) { if (!this._object) { return; } this.constructor.addAttribute(this._object, name, value); } addNumericAttrib(name, value) { if (!this._object) { return; } this.constructor.addNumericAttribute( this._object, name, 1, value ); } setAttribValue(name, value) { this.addAttribute(name, value); } // addNumericVertexAttrib(name: string, size: number, defaultValue: NumericAttribValue) { // // if (defaultValue == null) { // // defaultValue = CoreAttribute.default_value(size); // // } // // this.coreGeometry()?.addNumericAttrib(name, size, defaultValue); // } static _attributesDictionary(object) { return object.userData[ATTRIBUTES] || this._createAttributesDictionaryIfNone(object); } static attributesDictionaryEntry(object, attribName, defaultValue) { const dict = object.userData[ATTRIBUTES] || this._createAttributesDictionaryIfNone(object); let entry = dict[attribName]; if (entry == null && defaultValue != null) { entry = defaultValue; dict[attribName] = entry; } return entry; } // static attributesPreviousValuesDictionary<T extends CoreObjectType>(object: ObjectContent<T>) { // return ( // (object.userData[ATTRIBUTES_PREVIOUS_VALUES] as AttributeDictionary) || // this._createAttributesPreviousValuesDictionaryIfNone(object) // ); // } static _createAttributesDictionaryIfNone(object) { if (!object.userData[ATTRIBUTES]) { return object.userData[ATTRIBUTES] = {}; } } // private static _createAttributesPreviousValuesDictionaryIfNone<T extends CoreObjectType>(object: ObjectContent<T>) { // if (!object.userData[ATTRIBUTES_PREVIOUS_VALUES]) { // return (object.userData[ATTRIBUTES_PREVIOUS_VALUES] = {}); // } // } _attributesDictionary() { return this.constructor._attributesDictionary(this._object); } static attributes(object) { return this._attributesDictionary(object); } attributes() { if (!this._object) { return; } return this.constructor.attributes(this._object); } attributeNames() { return this.attribNames(); } static attribNames(object) { return Object.keys(this._attributesDictionary(object)); } attribNames() { return this.constructor.attribNames(this._object); } static hasAttribute(object, attribName) { return attribName in this._attributesDictionary(object); } hasAttribute(attribName) { return this.constructor.hasAttribute( this._object, attribName ); } static attributeNames(object) { const attributes = this.attributes(object); if (!attributes) { return []; } return Object.keys(attributes); } static attributeNamesMatchingMask(object, masksString) { return CoreAttribute.attribNamesMatchingMask(masksString, this.attributeNames(object)); } renameAttribute(oldName, newName) { return this.constructor.renameAttribute( this._object, oldName, newName ); } static renameAttribute(object, oldName, newName) { const currentValue = this.attribValue(object, oldName); if (currentValue != null) { this.addAttribute(object, newName, currentValue); this.deleteAttribute(object, oldName); } else { console.warn(`attribute ${oldName} not found`); } } deleteAttribute(name) { delete this._attributesDictionary()[name]; } static deleteAttribute(object, attribName) { delete this._attributesDictionary(object)[attribName]; } // static position:PositionStaticMethod<CoreObjectType> = DEFAULT_POSITION_STATIC_METHOD static position(object, target) { target.copy(ORIGIN); } position(target) { this.constructor.position(this._object, target); return target; } static boundingBox(object, target) { target.makeEmpty(); } boundingBox(target) { this.constructor.boundingBox(this._object, target); } static geometryBoundingBox(object, target) { this.boundingBox(object, target); } geometryBoundingBox(target) { this.constructor.geometryBoundingBox(this._object, target); } static boundingSphere(object, target) { target.makeEmpty(); } boundingSphere(target) { this.constructor.boundingSphere(this._object, target); } static geometryBoundingSphere(object, target) { target.makeEmpty(); } geometryBoundingSphere(target) { this.constructor.geometryBoundingSphere(this._object, target); } static attribValue(object, attribName, index = 0, target) { const _attribFromProperty = () => { if (attribName == "name" /* NAME */) { return object.name; } if (attribName == "position" /* POSITION */) { const _target = target instanceof Vector3 ? target : tmpVec3; this.position(object, _target); _target.toArray(tmpN3); return tmpN3; } }; if (attribName === Attribute.OBJECT_INDEX) { return index; } if (attribName === Attribute.OBJECT_NAME) { return object.name; } if (object.userData) { const val = this.attributesDictionaryEntry(object, attribName); if (val == null) { return _attribFromProperty(); } else { if (isVector(val) && target) { if (val instanceof Vector2 && target instanceof Vector2) { return target.copy(val); } if (val instanceof Vector3 && target instanceof Vector3) { return target.copy(val); } if (val instanceof Vector4 && target instanceof Vector4) { return target.copy(val); } } if (isColor(val) && target) { if (val instanceof Color && target instanceof Color) { return target.copy(val); } } if (isArray(val) && target) { target.fromArray(val); return target; } } return val; } return _attribFromProperty(); } // static previousAttribValue<T extends CoreObjectType>( // object: ObjectContent<T>, // attribName: string // ): AttribValue | undefined { // const dict = this.attributesPreviousValuesDictionary(object); // return dict[attribName]; // } static stringAttribValue(object, attribName, index = 0) { const str = this.attribValue(object, attribName, index); if (str != null) { if (isString(str)) { return str; } else { return `${str}`; } } return null; } // static makeAttribReactive<V extends AttribValue, T extends CoreObjectType>( // object: ObjectContent<T>, // attribName: string, // callback: AttributeReactiveCallback<V> // ) { // const attributesDict = this.attributesDictionary(object); // // const attributesPreviousValuesDict = this.attributesPreviousValuesDictionary(object); // const currentValue = attributesDict[attribName]; // if (currentValue instanceof Vector4) { // return makeAttribReactiveVector4( // object, // attribName, // (<unknown>callback) as AttributeReactiveCallback<Vector4> // ); // } // if (currentValue instanceof Vector3) { // return makeAttribReactiveVector3( // object, // attribName, // (<unknown>callback) as AttributeReactiveCallback<Vector3> // ); // } // if (currentValue instanceof Vector2) { // return makeAttribReactiveVector2( // object, // attribName, // (<unknown>callback) as AttributeReactiveCallback<Vector2> // ); // } // return makeAttribReactiveSimple( // object, // attribName, // (<unknown>callback) as AttributeReactiveCallback<string | number> // ); // // // create a dummy val in case there is no attribute yet // // if (attributesDict[attribName] == null) { // // attributesDict[attribName] = 0; // // } // // const proxy: AttributeProxy<V> = { // // value: attributesDict[attribName] as V, // // previousValue: attributesDict[attribName] as V, // // }; // // Object.defineProperties(attributesDict, { // // [attribName]: { // // get: function () { // // return proxy.value; // // }, // // set: function (x) { // // if (x != proxy.value) { // // proxy.previousValue = proxy.value; // // proxy.value = x; // // callback(proxy.value, proxy.previousValue); // // } // // return proxy.value; // // }, // // configurable: true, // // }, // // }); // // Object.defineProperties(attributesPreviousValuesDict, { // // [attribName]: { // // get: function () { // // return proxy.previousValue; // // }, // // configurable: true, // // }, // // }); // } attribValue(attribName, target) { return this.constructor.attribValue( this._object, attribName, this._index, target ); } stringAttribValue(name) { return this.constructor.stringAttribValue( this._object, name, this._index ); } name() { return this.attribValue("name" /* NAME */); } humanType() { return this._object.type; } attribTypes() { const h = {}; for (const attrib_name of this.attribNames()) { const type = this.attribType(attrib_name); if (type != null) { h[attrib_name] = type; } } return h; } static attribType(object, attribName) { const val = this.attribValue(object, attribName); if (isString(val)) { return AttribType.STRING; } else { return AttribType.NUMERIC; } } attribType(attribName) { return this.constructor.attribType(this._object, attribName); } attribSizes() { const h = {}; const attribNames = this.attribNames(); for (const attribName of attribNames) { const size = this.attribSize(attribName); if (size != null) { h[attribName] = size; } } return h; } static attribSize(object, attribName) { const val = this.attribValue(object, attribName); if (val == null) { return null; } return CoreAttribute.attribSizeFromValue(val); } attribSize(attribName) { return this.constructor.attribSize(this._object, attribName); } static objectData(object) { return objectData(object); } clone() { const clonedObject = this.constructor.clone(this._object); const cloned = new this.constructor(clonedObject, this._index); return cloned; } static clone(srcObject) { return srcObject.clone(); } static applyMatrix(object, matrix, transformTargetType, transformSpace, transformMode) { console.warn("applyMatrix.override required", this); } static mergeCompact(options) { console.warn("mergeCompact.override required", this); } // // // ENTITY GROUPS // // groupCollection() { return new EntityGroupCollection(this._object); } // // // RELATED ENTITIES // // static relatedVertexIds(object, objectIndex, target, traversedRelatedEntityData) { const ids = traversedRelatedEntityData ? traversedRelatedEntityData[AttribClass.PRIMITIVE].ids : _relatedPrimitiveIds; this.relatedPrimitiveIds(object, objectIndex, ids, traversedRelatedEntityData); uniqRelatedEntityIds( ids, (primitiveId, relatedEntityIds) => { this.relatedPrimitiveClass(object).relatedVertexIds(object, primitiveId, relatedEntityIds); }, target ); } static relatedPointIds(object, objectIndex, target, traversedRelatedEntityData) { const ids = traversedRelatedEntityData ? traversedRelatedEntityData[AttribClass.VERTEX].ids : _relatedVertexIds; this.relatedVertexIds(object, objectIndex, ids, traversedRelatedEntityData); uniqRelatedEntityIds( ids, (vertexId, relatedEntityIds) => { this.relatedVertexClass(object).relatedPointIds(object, vertexId, relatedEntityIds); }, target ); } relatedEntities(attribClass, coreGroup, target, traversedRelatedEntityData) { switch (attribClass) { case AttribClass.POINT: { this.relatedPoints(target, traversedRelatedEntityData); return; } case AttribClass.VERTEX: { this.relatedVertices(target, traversedRelatedEntityData); return; } case AttribClass.PRIMITIVE: { this.relatedPrimitives(target, traversedRelatedEntityData); return; } case AttribClass.OBJECT: { target.length = 1; target[0] = this; return; } case AttribClass.CORE_GROUP: { target.length = 1; target[0] = coreGroup; return; } } TypeAssert.unreachable(attribClass); } static relatedPointClass(object) { return this.relatedVertexClass(object).relatedPointClass(object); } static relatedVertexClass(object) { return this.relatedPrimitiveClass(object).relatedVertexClass(object); } }