diff --git a/src/components/body-helper.js b/src/components/body-helper.js index 96496da1e0..d10207eef2 100644 --- a/src/components/body-helper.js +++ b/src/components/body-helper.js @@ -1,7 +1,7 @@ import { addComponent, removeComponent } from "bitecs"; import { CONSTANTS } from "three-ammo"; import { Rigidbody } from "../bit-components"; -import { updateBodyParams } from "../inflators/rigid-body"; + const ACTIVATION_STATE = CONSTANTS.ACTIVATION_STATE, TYPE = CONSTANTS.TYPE; @@ -30,24 +30,45 @@ AFRAME.registerComponent("body-helper", { type: { default: "dynamic", oneOf: [TYPE.STATIC, TYPE.DYNAMIC, TYPE.KINEMATIC] }, emitCollisionEvents: { default: false }, disableCollision: { default: false }, - collisionFilterGroup: { default: 1 }, //32-bit mask, - collisionFilterMask: { default: 1 }, //32-bit mask + collisionFilterGroup: { default: 1 }, + collisionFilterMask: { default: 1 }, scaleAutoUpdate: { default: true } }, + validateConfig(data) { + if (typeof data.mass !== "number" || isNaN(data.mass)) { + console.warn(`[body-helper] Invalid mass: ${data.mass}. Defaulting to 1.`); + data.mass = 1; + } + + const validTypes = [TYPE.STATIC, TYPE.DYNAMIC, TYPE.KINEMATIC]; + if (!validTypes.includes(data.type)) { + console.warn(`[body-helper] Invalid type: ${data.type}. Defaulting to dynamic.`); + data.type = TYPE.DYNAMIC; + } + + if (!data.gravity || typeof data.gravity !== "object") { + console.warn("[body-helper] Invalid gravity vector. Using default gravity."); + data.gravity = { x: 0, y: -9.8, z: 0 }; + } + }, + init: function () { + this.validateConfig(this.data); + this.system = this.el.sceneEl.systems["hubs-systems"].physicsSystem; this.alive = true; this.el.object3D.updateMatrices(); this.uuid = this.system.addBody(this.el.object3D, this.data); + const eid = this.el.object3D.eid; addComponent(APP.world, Rigidbody, eid); - updateBodyParams(eid, this.data); - Rigidbody.bodyId[eid] = this.uuid; //uuid is a lie, it's actually an int + Rigidbody.bodyId[eid] = this.uuid; }, update: function (prevData) { if (prevData) { + this.validateConfig(this.data); const eid = this.el.object3D.eid; this.system.updateRigidBody(eid, this.data); } @@ -60,3 +81,4 @@ AFRAME.registerComponent("body-helper", { this.alive = false; } }); + diff --git a/src/components/camera.js b/src/components/camera.js new file mode 100644 index 0000000000..f69525b38e --- /dev/null +++ b/src/components/camera.js @@ -0,0 +1,26 @@ +AFRAME.registerComponent("stabilize-camera", { + init: function () { + this.el.addEventListener("grab-start", (evt) => { + if (!NAF.utils.isMine(this.el)) { + console.warn("Cannot interact: you do not own this camera."); + evt.stopImmediatePropagation(); + evt.preventDefault(); + } + }); + + this.el.addEventListener("grab-move", (evt) => { + if (!NAF.utils.isMine(this.el)) { + evt.stopImmediatePropagation(); + evt.preventDefault(); + } + }); + + this.el.addEventListener("grab-end", (evt) => { + if (!NAF.utils.isMine(this.el)) { + evt.stopImmediatePropagation(); + evt.preventDefault(); + } + }); + } +}); + diff --git a/src/components/gltf-model-plus.js b/src/components/gltf-model-plus.js index c668615aa4..f15d171c68 100644 --- a/src/components/gltf-model-plus.js +++ b/src/components/gltf-model-plus.js @@ -596,14 +596,17 @@ class GLTFHubsComponentsExtension { if (shouldUseNewLoader()) { if (Object.prototype.hasOwnProperty.call(ext, "link")) { if (["image", "video", "model"].includes(componentName)) { - ext["media-link"] = { - src: ext.link.href - }; - delete ext.link; + if (!ext.link || !ext.link.href) { + console.warn("Warning: Attempted to load a link but the href is missing! Component : ${componentName}", ext); + } else { + ext["media-link"] = { + src: ext.link.href + }; + delete ext.link; + } } } } - const value = props[propName]; const type = value?.__mhc_link_type; if (type && value.index !== undefined) { diff --git a/webpack.config.js b/webpack.config.js index 0a3f660491..666ff84cbd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -285,9 +285,6 @@ module.exports = async (env, argv) => { // .replaceAll("connect-src", "connect-src https://example.com"); } - const addonsConfigFilePath = "./addons.json"; - const addonsConfig = JSON.parse(fs.readFileSync(addonsConfigFilePath, "utf-8")); - const internalHostname = process.env.INTERNAL_HOSTNAME || "hubs.local"; return { cache: { @@ -306,9 +303,7 @@ module.exports = async (env, argv) => { "three/examples/js/libs/basis/basis_transcoder.js": basisTranscoderPath, "three/examples/js/libs/draco/gltf/draco_wasm_wrapper.js": dracoWasmWrapperPath, "three/examples/js/libs/basis/basis_transcoder.wasm": basisWasmPath, - "three/examples/js/libs/draco/gltf/draco_decoder.wasm": dracoWasmPath, - - hubs$: path.resolve(__dirname, "./src/hubs.js") + "three/examples/js/libs/draco/gltf/draco_decoder.wasm": dracoWasmPath }, // Allows using symlinks in node_modules symlinks: false, @@ -325,7 +320,7 @@ module.exports = async (env, argv) => { entry: { support: path.join(__dirname, "src", "support.js"), index: path.join(__dirname, "src", "index.js"), - hub: [path.join(__dirname, "src", "hub.js"), ...addonsConfig.addons], + hub: path.join(__dirname, "src", "hub.js"), scene: path.join(__dirname, "src", "scene.js"), avatar: path.join(__dirname, "src", "avatar.js"), link: path.join(__dirname, "src", "link.js"), @@ -341,9 +336,6 @@ module.exports = async (env, argv) => { filename: "assets/js/[name]-[chunkhash].js", publicPath: process.env.BASE_ASSETS_PATH || "" }, - optimization: { - minimize: argv.mode === "production" ? true : false - }, target: ["web", "es5"], // use es5 for webpack runtime to maximize compatibility devtool: argv.mode === "production" ? "source-map" : "inline-source-map", devServer: { @@ -633,6 +625,9 @@ module.exports = async (env, argv) => { priority: 10 } } + }, + runtimeChunk: { + name: "runtime" } }, plugins: [