From 056fd9d6b0d9312afd451894929012505efdcba1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 10 Apr 2024 19:13:29 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=B7=20MRjs=20-=20Auto=20Generated=20Di?= =?UTF-8?q?st=20=F0=9F=91=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes at 70494db99029a5ac2a7b294bb9c1c54280f0214f --- dist/mr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/mr.js b/dist/mr.js index d9a832cd..81c71ff2 100644 --- a/dist/mr.js +++ b/dist/mr.js @@ -465,7 +465,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MREntity: () => (/* binding */ MREntity)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var mrjs_core_MRElement__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! mrjs/core/MRElement */ \"./src/core/MRElement.js\");\n/* harmony import */ var mrjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! mrjs */ \"./src/index.js\");\n\n\n\n\n\n\nconst MOUSE_EVENTS = ['click', 'mouseenter', 'mouseleave', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove'];\n\n/**\n * @class MREntity\n * @classdesc The default representation of an MRElement to be expanded upon by actual details ECS Entity items. `mr-entity`\n * @augments MRElement\n */\nclass MREntity extends mrjs_core_MRElement__WEBPACK_IMPORTED_MODULE_0__.MRElement {\n aabb = new three__WEBPACK_IMPORTED_MODULE_2__.Box3();\n\n size = new three__WEBPACK_IMPORTED_MODULE_2__.Vector3();\n\n layer = 0;\n\n physics = {\n type: 'none',\n };\n\n /**\n * @class\n * @description Constructor for the default Entity Component (MREntity).\n * Sets up the base object3D and useful Mixed Reality information including rendering, touching, and component basics.\n */\n constructor() {\n super();\n\n this.object3D = new three__WEBPACK_IMPORTED_MODULE_2__.Group();\n this.object3D.userData.isEntityObject3DRoot = true;\n this.object3D.userData.bbox = new three__WEBPACK_IMPORTED_MODULE_2__.Box3();\n this.object3D.userData.size = new three__WEBPACK_IMPORTED_MODULE_2__.Vector3();\n\n this.object3D.receiveShadow = true;\n this.object3D.castShadow = true;\n this.object3D.renderOrder = 3;\n this.object3D.name = 'entity';\n\n this.scale = 1;\n\n this.componentMutated = this.componentMutated.bind(this);\n\n this.touch = false;\n this.grabbed = false;\n this.focus = false;\n\n this.ignoreStencil = true;\n }\n\n /*************************/\n /*** Object Dimensions ***/\n /*************************/\n\n /**\n * @function\n * @description Calculates the width of the Entity based on the viewPort's shape. If in Mixed Reality, adjusts the value appropriately.\n * @returns {number} - the resolved width\n */\n get width() {\n return (this.compStyle.width.split('px')[0] / __webpack_require__.g.appWidth) * __webpack_require__.g.viewPortWidth;\n }\n\n /**\n * @function\n * @description The actual 3D value of the content's width.\n * @returns {number} - width of the 3D object.\n */\n get contentWidth() {\n this.aabb.setFromObject(this.object3D).getSize(this.size);\n return this.size.x;\n }\n\n /**\n * @function\n * @description Calculates the height of the Entity based on the viewPort's shape. If in Mixed Reality, adjusts the value appropriately.\n * @returns {number} - the resolved height\n */\n get height() {\n return (this.compStyle.height.split('px')[0] / __webpack_require__.g.appHeight) * __webpack_require__.g.viewPortHeight;\n }\n\n /**\n * @function\n * @description The actual 3D value of the content's height.\n * @returns {number} - height of the 3D object.\n */\n get contentHeight() {\n this.aabb.setFromObject(this.object3D).getSize(this.size);\n return this.size.y;\n }\n\n /****************************/\n /*** Updates And Triggers ***/\n /****************************/\n\n /**\n * @function\n * @description Triggers a system run to update geometry specifically for the entity calling it. Useful when it's not an overall scene event and for cases where\n * relying on an overall scene or all items to update isnt beneficial.\n */\n triggerGeometryStyleUpdate() {\n this.dispatchEvent(new CustomEvent('trigger-geometry-style-update', { detail: this, bubbles: true }));\n }\n\n /**\n * @function\n * @description Triggers a system run to update material specifically for the entity calling it. Useful when it's not an overall scene event and for cases where\n * relying on an overall scene or all items to update isnt beneficial.\n */\n triggerMaterialStyleUpdate() {\n this.dispatchEvent(new CustomEvent('trigger-material-style-update', { detail: this, bubbles: true }));\n }\n\n /**\n * @function\n * @description Directly in MRjs, this function is empty. It is called directly in the\n * MaterialStyleSystem. This allows outside users to add their own additional functionality\n * for the entities. These are run after the MaterialStyleSystem does its own update on the entity.\n */\n updateMaterialStyle() {}\n\n /**\n * @function\n * @description Directly in MRjs, this function is empty. It is called directly in the\n * GeometryStyleSystem. This allows outside users to add their own additional functionality\n * for the entities. These are run after the GeometryStyleSystem does its own update on the entity.\n */\n updateGeometryStyle() {}\n\n /*****************************/\n /*** On Interaction Events ***/\n /*****************************/\n\n /**\n * @function\n * @description Handles the hover event\n * @param {object} event - the hover event\n */\n onHover = (event) => {};\n\n /**\n * @function\n * @description Handles the touch event\n * @param {object} event - the touch event\n */\n onTouch = (event) => {};\n\n /**\n * @function\n * @description Handles the scroll event\n * @param {object} event - the scroll event\n */\n onScroll = (event) => {\n this.parentElement?.onScroll(event);\n };\n\n /********************************/\n /*** Handling data-attributes ***/\n /********************************/\n\n components = {\n get: (name) => {\n const dataName = `comp${name[0].toUpperCase()}${name.slice(1)}`;\n return mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToJson(this.dataset[dataName]);\n },\n\n set: (name, data) => {\n const dataName = `comp${name[0].toUpperCase()}${name.slice(1)}`;\n const component = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToJson(this.dataset[dataName]) ?? {};\n for (const key in data) {\n component[key] = data[key];\n }\n this.dataset[dataName] = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.jsonToString(component);\n },\n\n toJSON: () => {\n let all = {}\n for (const key in this.dataset) {\n let compName = key.split('comp')[1]\n if(compName) {\n all[compName.toLowerCase()] = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToJson(this.dataset[key])\n }\n }\n return all\n }\n };\n\n position = {\n get: () => {\n return mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n },\n\n set: (arr) => {\n if (arr.length != 3) {\n mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.error.err('position must be set with an array of all three elements [x, y, z]');\n }\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position ?? '0 0 0');\n vec[0] = arr[0];\n vec[1] = arr[1];\n vec[2] = arr[2];\n this.dataset.position = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n x: () => {\n return this.dataset.position.split(' ')[0];\n },\n\n setX: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n vec[0] = val;\n this.dataset.position = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n y: () => {\n return this.dataset.position.split(' ')[1];\n },\n\n setY: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n vec[1] = val;\n this.dataset.position = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n z: () => {\n return this.dataset.position.split(' ')[2];\n },\n\n setZ: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n vec[2] = val;\n this.dataset.position = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n };\n\n rotation = {\n get: () => {\n return mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n },\n\n set: (arr) => {\n if (arr.length != 3) {\n mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.error.err('rotation must be set with an array of all three elements [x, y, z]');\n }\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation ?? '0 0 0');\n vec[0] = arr[0];\n vec[1] = arr[1];\n vec[2] = arr[2];\n this.dataset.rotation = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n x: () => {\n return this.dataset.rotation.split(' ')[0];\n },\n\n x: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation);\n vec[0] = val;\n this.dataset.rotation = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n y: () => {\n return this.dataset.rotation.split(' ')[1];\n },\n\n y: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation);\n vec[1] = val;\n this.dataset.rotation = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n z: () => {\n return this.dataset.rotation.split(' ')[2];\n },\n\n z: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation);\n vec[2] = val;\n this.dataset.rotation = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n };\n\n /**\n * @function\n * @description Loads all attributes of this entity's stored dataset including components, attaching them, and their associated rotations and positions.\n */\n loadAttributes() {\n for (const attr in this.dataset) {\n if (attr.includes('comp')) {\n const compName = attr.split('comp')[1].toLocaleLowerCase();\n this.dispatchEvent(\n new CustomEvent(`${attr}-attached`, {\n bubbles: true,\n detail: { entity: this },\n })\n );\n } else {\n switch (attr) {\n case 'rotation':\n this.object3D.rotation.fromArray(mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToDegVector(this.dataset.rotation));\n break;\n case 'position':\n this.object3D.position.fromArray(mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position));\n break;\n }\n }\n }\n }\n\n /************************************/\n /*** Handling Entity Interactions ***/\n /************************************/\n\n /**\n * @function\n * @description (async) does nothing. Is called by the connectedCallback.\n */\n async connected() {}\n\n /**\n * @function\n * @description The connectedCallback function that runs whenever this entity component becomes connected to something else.\n */\n async connectedCallback() {\n this.compStyle = window.getComputedStyle(this);\n\n if (!(this.parentElement instanceof mrjs_core_MRElement__WEBPACK_IMPORTED_MODULE_0__.MRElement)) {\n return;\n }\n this.parentElement.add(this);\n\n if (this.parentElement.user) {\n this.user = this.parentElement.user;\n }\n if (this.parentElement.env) {\n this.env = this.parentElement.env;\n }\n\n this.object3D.userData.element = this;\n\n this.object3D.userData.bbox = new three__WEBPACK_IMPORTED_MODULE_2__.Box3();\n this.object3D.userData.size = new three__WEBPACK_IMPORTED_MODULE_2__.Vector3();\n\n this.object3D.userData.bbox.setFromObject(this.object3D);\n\n this.object3D.userData.bbox.getSize(this.object3D.userData.size);\n\n this.mutationCallback = this.mutationCallback.bind(this);\n this.observer = new MutationObserver(this.mutationCallback);\n this.observer.observe(this, { attributes: true, childList: true, attributeOldValue: true });\n\n /** Handle events specific to this entity */\n // note: these will need the trigger for Material or Geometry if applicable\n\n MOUSE_EVENTS.forEach((eventType) => {\n this.addEventListener(eventType, (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n });\n });\n\n this.addEventListener('touchstart', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onTouch(event);\n });\n this.addEventListener('touchmove', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onTouch(event);\n });\n this.addEventListener('touchend', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onTouch(event);\n });\n this.addEventListener('hoverstart', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onHover(event);\n });\n this.addEventListener('hoverend', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onHover(event);\n });\n\n this.addEventListener('child-updated', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n });\n\n // TODO: find alternative solution. This breaks with the switch to asychronous entity initialization\n // const intersectionObserver = new IntersectionObserver((entries) => {\n // for (const entry of entries) {\n // this._boundingClientRect = entry.boundingClientRect;\n // }\n // // Refresh the rect info to keep it up-to-date as much as possible.\n // // It seems that the callback is always called once soon after observe() is called,\n // // regardless of the intersection state of the entity.\n // // TODO: Confirm whether this behavior is intended. If it is not, there may be future\n // // behavior changes or it may not work as intended on certain platforms.\n // intersectionObserver.disconnect();\n // intersectionObserver.observe(this);\n // });\n // intersectionObserver.observe(this);\n\n // If the physics not yet inititalized, set an event listener and wait til the engine\n // has started before completing initialization\n if (mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.physics.initialized) {\n await this.connected();\n this.loadAttributes();\n this.dispatchEvent(new CustomEvent('entityadded', { bubbles: true }));\n } else {\n document.addEventListener('engine-started', async (event) => {\n await this.connected();\n this.loadAttributes();\n this.dispatchEvent(new CustomEvent('entityadded', { bubbles: true }));\n });\n }\n }\n\n /**\n * @function\n * @description Callback function of MREntity - does nothing. Is called by the disconnectedCallback.\n */\n disconnected() {}\n\n /**\n * @function\n * @description The disconnectedCallback function that runs whenever this entity component becomes disconnected from something else.\n */\n disconnectedCallback() {\n document.dispatchEvent(\n new CustomEvent('entityremoved', {\n detail: {\n entity: this,\n },\n })\n );\n\n this.environment = null;\n this.observer.disconnect();\n\n this.disconnected();\n }\n\n /**\n * @function\n * @description Callback function of MREntity - does nothing. Is called by mutation Callback.\n * @param {object} mutation - the update/change/mutation to be handled.\n */\n mutated(mutation) {}\n\n /**\n * @function\n * @description The mutationCallback function that runs whenever this entity component should be mutated.\n * @param {object} mutationList - the list of update/change/mutation(s) to be handled.\n * @param {object} observer - w3 standard object that watches for changes on the HTMLElement\n */\n mutationCallback(mutationList, observer) {\n for (const mutation of mutationList) {\n this.mutated(mutation);\n\n switch (mutation.type) {\n case 'childList':\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n break;\n case 'attributes':\n if (mutation.attributeName.includes('comp')) {\n this.componentMutated(mutation);\n }\n switch (mutation.attributeName) {\n case 'data-position':\n this.object3D.position.fromArray(mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position));\n break;\n case 'data-rotation':\n this.object3D.rotation.fromArray(mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToDegVector(this.dataset.rotation));\n break;\n\n default:\n break;\n }\n break;\n\n default:\n break;\n }\n }\n }\n\n /**\n * @function\n * @description Helper function for the mutationCallback. Handles actually updating this entity component with all the associated dispatchEvents.\n * @param {object} mutation - the update/change/mutation to be handled.\n */\n componentMutated(mutation) {\n const compName = mutation.attributeName.split('comp-')[1];\n const dataName = `comp${compName[0].toUpperCase()}${compName.slice(1)}`;\n if (!this.dataset[dataName]) {\n this.dispatchEvent(new CustomEvent(`${dataName}-detached`, { bubbles: true }));\n } else if (mutation.oldValue) {\n this.dispatchEvent(\n new CustomEvent(`${dataName}-updated`, {\n bubbles: true,\n detail: { oldData: mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.jsonToString(mutation.oldValue) },\n })\n );\n } else {\n this.dispatchEvent(\n new CustomEvent(`${dataName}-attached`, {\n bubbles: true,\n })\n );\n }\n }\n\n /**\n * @function\n * @description Adding an entity as a sub-object of this entity.\n * @param {MREntity} entity - the entity to be added.\n */\n add(entity) {\n entity.object3D.receiveShadow = true;\n entity.object3D.renderOrder = 3;\n this.object3D.add(entity.object3D);\n }\n\n /**\n * @function\n * @description Removing an entity as a sub-object of this entity.\n * @param {MREntity} entity - the entity to be removed.\n */\n removeEntity(entity) {\n this.object3D.remove(entity.object3D);\n }\n\n /**\n * @function\n * @description Runs the passed through function on this object and every child of this object.\n * @param {Function} callBack - the function to run recursively.\n */\n traverse(callBack) {\n callBack(this);\n const children = Array.from(this.children);\n for (const child of children) {\n // if child is an entity, traverse it again\n if (child instanceof MREntity) {\n child.traverse(callBack);\n }\n }\n }\n\n /**\n * @function\n * @description Runs the passed through function on the objects associated with this Entity\n * @param {Function} callBack - the function to run recursively.\n */\n traverseObjects(callBack) {\n const traverse = (object) => {\n callBack(object);\n for (const child of object.children) {\n if (!child.userData.isEntityObject3DRoot) {\n traverse(child);\n }\n }\n };\n traverse(this.object3D);\n }\n}\n\ncustomElements.get('mr-entity') || customElements.define('mr-entity', MREntity);\n\n\n//# sourceURL=webpack://mrjs/./src/core/MREntity.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MREntity: () => (/* binding */ MREntity)\n/* harmony export */ });\n/* harmony import */ var three__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! three */ \"./node_modules/three/build/three.module.js\");\n/* harmony import */ var mrjs_core_MRElement__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! mrjs/core/MRElement */ \"./src/core/MRElement.js\");\n/* harmony import */ var mrjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! mrjs */ \"./src/index.js\");\n\n\n\n\n\n\nconst MOUSE_EVENTS = ['click', 'mouseenter', 'mouseleave', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove'];\n\n/**\n * @class MREntity\n * @classdesc The default representation of an MRElement to be expanded upon by actual details ECS Entity items. `mr-entity`\n * @augments MRElement\n */\nclass MREntity extends mrjs_core_MRElement__WEBPACK_IMPORTED_MODULE_0__.MRElement {\n aabb = new three__WEBPACK_IMPORTED_MODULE_2__.Box3();\n\n size = new three__WEBPACK_IMPORTED_MODULE_2__.Vector3();\n\n layer = 0;\n\n physics = {\n type: 'none',\n };\n\n /**\n * @class\n * @description Constructor for the default Entity Component (MREntity).\n * Sets up the base object3D and useful Mixed Reality information including rendering, touching, and component basics.\n */\n constructor() {\n super();\n\n this.object3D = new three__WEBPACK_IMPORTED_MODULE_2__.Group();\n this.object3D.userData.isEntityObject3DRoot = true;\n this.object3D.userData.bbox = new three__WEBPACK_IMPORTED_MODULE_2__.Box3();\n this.object3D.userData.size = new three__WEBPACK_IMPORTED_MODULE_2__.Vector3();\n\n this.object3D.receiveShadow = true;\n this.object3D.castShadow = true;\n this.object3D.renderOrder = 3;\n this.object3D.name = 'entity';\n\n this.scale = 1;\n\n this.componentMutated = this.componentMutated.bind(this);\n\n this.touch = false;\n this.grabbed = false;\n this.focus = false;\n\n this.ignoreStencil = true;\n }\n\n /*************************/\n /*** Object Dimensions ***/\n /*************************/\n\n /**\n * @function\n * @description Calculates the width of the Entity based on the viewPort's shape. If in Mixed Reality, adjusts the value appropriately.\n * @returns {number} - the resolved width\n */\n get width() {\n return (this.compStyle.width.split('px')[0] / __webpack_require__.g.appWidth) * __webpack_require__.g.viewPortWidth;\n }\n\n /**\n * @function\n * @description The actual 3D value of the content's width.\n * @returns {number} - width of the 3D object.\n */\n get contentWidth() {\n this.aabb.setFromObject(this.object3D).getSize(this.size);\n return this.size.x;\n }\n\n /**\n * @function\n * @description Calculates the height of the Entity based on the viewPort's shape. If in Mixed Reality, adjusts the value appropriately.\n * @returns {number} - the resolved height\n */\n get height() {\n return (this.compStyle.height.split('px')[0] / __webpack_require__.g.appHeight) * __webpack_require__.g.viewPortHeight;\n }\n\n /**\n * @function\n * @description The actual 3D value of the content's height.\n * @returns {number} - height of the 3D object.\n */\n get contentHeight() {\n this.aabb.setFromObject(this.object3D).getSize(this.size);\n return this.size.y;\n }\n\n /****************************/\n /*** Updates And Triggers ***/\n /****************************/\n\n /**\n * @function\n * @description Triggers a system run to update geometry specifically for the entity calling it. Useful when it's not an overall scene event and for cases where\n * relying on an overall scene or all items to update isnt beneficial.\n */\n triggerGeometryStyleUpdate() {\n this.dispatchEvent(new CustomEvent('trigger-geometry-style-update', { detail: this, bubbles: true }));\n }\n\n /**\n * @function\n * @description Triggers a system run to update material specifically for the entity calling it. Useful when it's not an overall scene event and for cases where\n * relying on an overall scene or all items to update isnt beneficial.\n */\n triggerMaterialStyleUpdate() {\n this.dispatchEvent(new CustomEvent('trigger-material-style-update', { detail: this, bubbles: true }));\n }\n\n /**\n * @function\n * @description Directly in MRjs, this function is empty. It is called directly in the\n * MaterialStyleSystem. This allows outside users to add their own additional functionality\n * for the entities. These are run after the MaterialStyleSystem does its own update on the entity.\n */\n updateMaterialStyle() {}\n\n /**\n * @function\n * @description Directly in MRjs, this function is empty. It is called directly in the\n * GeometryStyleSystem. This allows outside users to add their own additional functionality\n * for the entities. These are run after the GeometryStyleSystem does its own update on the entity.\n */\n updateGeometryStyle() {}\n\n /*****************************/\n /*** On Interaction Events ***/\n /*****************************/\n\n /**\n * @function\n * @description Handles the hover event\n * @param {object} event - the hover event\n */\n onHover = (event) => {};\n\n /**\n * @function\n * @description Handles the touch event\n * @param {object} event - the touch event\n */\n onTouch = (event) => {};\n\n /**\n * @function\n * @description Handles the scroll event\n * @param {object} event - the scroll event\n */\n onScroll = (event) => {\n this.parentElement?.onScroll(event);\n };\n\n /********************************/\n /*** Handling data-attributes ***/\n /********************************/\n\n components = {\n get: (name) => {\n const dataName = `comp${name[0].toUpperCase()}${name.slice(1)}`;\n return mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToJson(this.dataset[dataName]);\n },\n\n set: (name, data) => {\n const dataName = `comp${name[0].toUpperCase()}${name.slice(1)}`;\n const component = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToJson(this.dataset[dataName]) ?? {};\n for (const key in data) {\n component[key] = data[key];\n }\n this.dataset[dataName] = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.jsonToString(component);\n },\n\n toJSON: () => {\n let all = {};\n for (const key in this.dataset) {\n let compName = key.split('comp')[1];\n if (compName) {\n all[compName.toLowerCase()] = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToJson(this.dataset[key]);\n }\n }\n return all;\n },\n };\n\n position = {\n get: () => {\n return mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n },\n\n set: (arr) => {\n if (arr.length != 3) {\n mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.error.err('position must be set with an array of all three elements [x, y, z]');\n }\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position ?? '0 0 0');\n vec[0] = arr[0];\n vec[1] = arr[1];\n vec[2] = arr[2];\n this.dataset.position = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n x: () => {\n return this.dataset.position.split(' ')[0];\n },\n\n setX: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n vec[0] = val;\n this.dataset.position = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n y: () => {\n return this.dataset.position.split(' ')[1];\n },\n\n setY: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n vec[1] = val;\n this.dataset.position = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n z: () => {\n return this.dataset.position.split(' ')[2];\n },\n\n setZ: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position);\n vec[2] = val;\n this.dataset.position = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n };\n\n rotation = {\n get: () => {\n return mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation);\n },\n\n set: (arr) => {\n if (arr.length != 3) {\n mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.error.err('rotation must be set with an array of all three elements [x, y, z]');\n }\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation ?? '0 0 0');\n vec[0] = arr[0];\n vec[1] = arr[1];\n vec[2] = arr[2];\n this.dataset.rotation = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n x: () => {\n return this.dataset.rotation.split(' ')[0];\n },\n\n x: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation);\n vec[0] = val;\n this.dataset.rotation = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n y: () => {\n return this.dataset.rotation.split(' ')[1];\n },\n\n y: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation);\n vec[1] = val;\n this.dataset.rotation = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n\n z: () => {\n return this.dataset.rotation.split(' ')[2];\n },\n\n z: (val) => {\n let vec = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.rotation);\n vec[2] = val;\n this.dataset.rotation = mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.vectorToString(vec);\n },\n };\n\n /**\n * @function\n * @description Loads all attributes of this entity's stored dataset including components, attaching them, and their associated rotations and positions.\n */\n loadAttributes() {\n for (const attr in this.dataset) {\n if (attr.includes('comp')) {\n const compName = attr.split('comp')[1].toLocaleLowerCase();\n this.dispatchEvent(\n new CustomEvent(`${attr}-attached`, {\n bubbles: true,\n detail: { entity: this },\n })\n );\n } else {\n switch (attr) {\n case 'rotation':\n this.object3D.rotation.fromArray(mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToDegVector(this.dataset.rotation));\n break;\n case 'position':\n this.object3D.position.fromArray(mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position));\n break;\n }\n }\n }\n }\n\n /************************************/\n /*** Handling Entity Interactions ***/\n /************************************/\n\n /**\n * @function\n * @description (async) does nothing. Is called by the connectedCallback.\n */\n async connected() {}\n\n /**\n * @function\n * @description The connectedCallback function that runs whenever this entity component becomes connected to something else.\n */\n async connectedCallback() {\n this.compStyle = window.getComputedStyle(this);\n\n if (!(this.parentElement instanceof mrjs_core_MRElement__WEBPACK_IMPORTED_MODULE_0__.MRElement)) {\n return;\n }\n this.parentElement.add(this);\n\n if (this.parentElement.user) {\n this.user = this.parentElement.user;\n }\n if (this.parentElement.env) {\n this.env = this.parentElement.env;\n }\n\n this.object3D.userData.element = this;\n\n this.object3D.userData.bbox = new three__WEBPACK_IMPORTED_MODULE_2__.Box3();\n this.object3D.userData.size = new three__WEBPACK_IMPORTED_MODULE_2__.Vector3();\n\n this.object3D.userData.bbox.setFromObject(this.object3D);\n\n this.object3D.userData.bbox.getSize(this.object3D.userData.size);\n\n this.mutationCallback = this.mutationCallback.bind(this);\n this.observer = new MutationObserver(this.mutationCallback);\n this.observer.observe(this, { attributes: true, childList: true, attributeOldValue: true });\n\n /** Handle events specific to this entity */\n // note: these will need the trigger for Material or Geometry if applicable\n\n MOUSE_EVENTS.forEach((eventType) => {\n this.addEventListener(eventType, (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n });\n });\n\n this.addEventListener('touchstart', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onTouch(event);\n });\n this.addEventListener('touchmove', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onTouch(event);\n });\n this.addEventListener('touchend', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onTouch(event);\n });\n this.addEventListener('hoverstart', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onHover(event);\n });\n this.addEventListener('hoverend', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n this.onHover(event);\n });\n\n this.addEventListener('child-updated', (event) => {\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n });\n\n // TODO: find alternative solution. This breaks with the switch to asychronous entity initialization\n // const intersectionObserver = new IntersectionObserver((entries) => {\n // for (const entry of entries) {\n // this._boundingClientRect = entry.boundingClientRect;\n // }\n // // Refresh the rect info to keep it up-to-date as much as possible.\n // // It seems that the callback is always called once soon after observe() is called,\n // // regardless of the intersection state of the entity.\n // // TODO: Confirm whether this behavior is intended. If it is not, there may be future\n // // behavior changes or it may not work as intended on certain platforms.\n // intersectionObserver.disconnect();\n // intersectionObserver.observe(this);\n // });\n // intersectionObserver.observe(this);\n\n // If the physics not yet inititalized, set an event listener and wait til the engine\n // has started before completing initialization\n if (mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.physics.initialized) {\n await this.connected();\n this.loadAttributes();\n this.dispatchEvent(new CustomEvent('entityadded', { bubbles: true }));\n } else {\n document.addEventListener('engine-started', async (event) => {\n await this.connected();\n this.loadAttributes();\n this.dispatchEvent(new CustomEvent('entityadded', { bubbles: true }));\n });\n }\n }\n\n /**\n * @function\n * @description Callback function of MREntity - does nothing. Is called by the disconnectedCallback.\n */\n disconnected() {}\n\n /**\n * @function\n * @description The disconnectedCallback function that runs whenever this entity component becomes disconnected from something else.\n */\n disconnectedCallback() {\n document.dispatchEvent(\n new CustomEvent('entityremoved', {\n detail: {\n entity: this,\n },\n })\n );\n\n this.environment = null;\n this.observer.disconnect();\n\n this.disconnected();\n }\n\n /**\n * @function\n * @description Callback function of MREntity - does nothing. Is called by mutation Callback.\n * @param {object} mutation - the update/change/mutation to be handled.\n */\n mutated(mutation) {}\n\n /**\n * @function\n * @description The mutationCallback function that runs whenever this entity component should be mutated.\n * @param {object} mutationList - the list of update/change/mutation(s) to be handled.\n * @param {object} observer - w3 standard object that watches for changes on the HTMLElement\n */\n mutationCallback(mutationList, observer) {\n for (const mutation of mutationList) {\n this.mutated(mutation);\n\n switch (mutation.type) {\n case 'childList':\n this.triggerGeometryStyleUpdate();\n this.triggerMaterialStyleUpdate();\n break;\n case 'attributes':\n if (mutation.attributeName.includes('comp')) {\n this.componentMutated(mutation);\n }\n switch (mutation.attributeName) {\n case 'data-position':\n this.object3D.position.fromArray(mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToVector(this.dataset.position));\n break;\n case 'data-rotation':\n this.object3D.rotation.fromArray(mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.stringToDegVector(this.dataset.rotation));\n break;\n\n default:\n break;\n }\n break;\n\n default:\n break;\n }\n }\n }\n\n /**\n * @function\n * @description Helper function for the mutationCallback. Handles actually updating this entity component with all the associated dispatchEvents.\n * @param {object} mutation - the update/change/mutation to be handled.\n */\n componentMutated(mutation) {\n const compName = mutation.attributeName.split('comp-')[1];\n const dataName = `comp${compName[0].toUpperCase()}${compName.slice(1)}`;\n if (!this.dataset[dataName]) {\n this.dispatchEvent(new CustomEvent(`${dataName}-detached`, { bubbles: true }));\n } else if (mutation.oldValue) {\n this.dispatchEvent(\n new CustomEvent(`${dataName}-updated`, {\n bubbles: true,\n detail: { oldData: mrjs__WEBPACK_IMPORTED_MODULE_1__.mrjsUtils.string.jsonToString(mutation.oldValue) },\n })\n );\n } else {\n this.dispatchEvent(\n new CustomEvent(`${dataName}-attached`, {\n bubbles: true,\n })\n );\n }\n }\n\n /**\n * @function\n * @description Adding an entity as a sub-object of this entity.\n * @param {MREntity} entity - the entity to be added.\n */\n add(entity) {\n entity.object3D.receiveShadow = true;\n entity.object3D.renderOrder = 3;\n this.object3D.add(entity.object3D);\n }\n\n /**\n * @function\n * @description Removing an entity as a sub-object of this entity.\n * @param {MREntity} entity - the entity to be removed.\n */\n removeEntity(entity) {\n this.object3D.remove(entity.object3D);\n }\n\n /**\n * @function\n * @description Runs the passed through function on this object and every child of this object.\n * @param {Function} callBack - the function to run recursively.\n */\n traverse(callBack) {\n callBack(this);\n const children = Array.from(this.children);\n for (const child of children) {\n // if child is an entity, traverse it again\n if (child instanceof MREntity) {\n child.traverse(callBack);\n }\n }\n }\n\n /**\n * @function\n * @description Runs the passed through function on the objects associated with this Entity\n * @param {Function} callBack - the function to run recursively.\n */\n traverseObjects(callBack) {\n const traverse = (object) => {\n callBack(object);\n for (const child of object.children) {\n if (!child.userData.isEntityObject3DRoot) {\n traverse(child);\n }\n }\n };\n traverse(this.object3D);\n }\n}\n\ncustomElements.get('mr-entity') || customElements.define('mr-entity', MREntity);\n\n\n//# sourceURL=webpack://mrjs/./src/core/MREntity.js?"); /***/ }),