diff --git a/src/bit-components.js b/src/bit-components.js index 7febf81698..1bafeafa25 100644 --- a/src/bit-components.js +++ b/src/bit-components.js @@ -21,9 +21,7 @@ export const Owned = defineComponent(); export const EntityStateDirty = defineComponent(); export const NetworkedMediaFrame = defineComponent({ capturedNid: Types.ui32, - scale: [Types.f32, 3], - flags: Types.ui8, - mediaType: Types.ui8 + scale: [Types.f32, 3] }); NetworkedMediaFrame.capturedNid[$isStringType] = true; @@ -121,11 +119,7 @@ export const Rigidbody = defineComponent({ activationState: Types.ui8, collisionFilterGroup: Types.ui32, collisionFilterMask: Types.ui32, - flags: Types.ui8, - initialCollisionFilterMask: Types.ui32 -}); -export const NetworkedRigidBody = defineComponent({ - prevType: Types.ui8 + flags: Types.ui8 }); export const PhysicsShape = defineComponent({ bodyId: Types.ui16, diff --git a/src/bit-systems/camera-tool.js b/src/bit-systems/camera-tool.js index f403300cf4..0ce7cf8411 100644 --- a/src/bit-systems/camera-tool.js +++ b/src/bit-systems/camera-tool.js @@ -211,7 +211,7 @@ function rotateWithRightClick(world, camera) { userinput.get(paths.device.mouse.buttonRight) ) { const rightCursor = anyEntityWith(world, RemoteRight); - physicsSystem.updateRigidBody(camera, { type: "kinematic" }); + physicsSystem.updateRigidBodyOptions(camera, { type: "kinematic" }); transformSystem.startTransform(world.eid2obj.get(camera), world.eid2obj.get(rightCursor), { mode: "cursor" }); diff --git a/src/bit-systems/interactable-system.ts b/src/bit-systems/interactable-system.ts deleted file mode 100644 index d7aa7e3442..0000000000 --- a/src/bit-systems/interactable-system.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { addComponent, defineQuery, enterQuery } from "bitecs"; -import { HubsWorld } from "../app"; -import { Holdable, MediaContentBounds, Networked, Rigidbody } from "../bit-components"; -import { getBox } from "../utils/auto-box-collider"; -import { Mesh, Vector3 } from "three"; -import { takeSoftOwnership } from "../utils/take-soft-ownership"; -import { EntityID } from "../utils/networking-types"; -import { COLLISION_LAYERS } from "../constants"; - -const tmpVector = new Vector3(); - -const interactableQuery = defineQuery([Holdable, Rigidbody, Networked]); -const interactableEnterQuery = enterQuery(interactableQuery); -export function interactableSystem(world: HubsWorld) { - interactableEnterQuery(world).forEach((eid: EntityID) => { - // Somebody must own a scene grabbable otherwise the networked transform will fight with physics. - if (Networked.creator[eid] === APP.getSid("scene") && Networked.owner[eid] === APP.getSid("reticulum")) { - takeSoftOwnership(world, eid); - } - - const obj = world.eid2obj.get(eid); - let hasMesh = false; - obj?.traverse(child => { - if ((child as Mesh).isMesh) { - hasMesh = true; - } - }); - - // If it has media frame collision mask, it needs to have content bounds - if (hasMesh && Rigidbody.collisionFilterMask[eid] & COLLISION_LAYERS.MEDIA_FRAMES) { - const box = getBox(obj, obj); - if (!box.isEmpty()) { - box.getSize(tmpVector); - addComponent(world, MediaContentBounds, eid); - MediaContentBounds.bounds[eid].set(tmpVector.toArray()); - } else { - console.error(`Couldn't create content bounds for entity ${eid}. It seems to be empty or have negative scale.`); - } - } - }); -} diff --git a/src/bit-systems/media-loading.ts b/src/bit-systems/media-loading.ts index b82e7cfcc4..98832a80dd 100644 --- a/src/bit-systems/media-loading.ts +++ b/src/bit-systems/media-loading.ts @@ -359,7 +359,7 @@ export function mediaLoadingSystem(world: HubsWorld) { jobs.add(eid, clearRollbacks => loadAndAnimateMedia(world, eid, clearRollbacks)); }); - mediaLoadingExitQuery(world).forEach(function (eid: EntityID) { + mediaLoadingExitQuery(world).forEach(function (eid) { jobs.stop(eid); if (MediaImageLoaderData.has(eid)) { @@ -406,7 +406,7 @@ export function mediaLoadingSystem(world: HubsWorld) { } }); - mediaLoadingQuery(world).forEach((eid: EntityID) => { + mediaLoadingQuery(world).forEach(eid => { const mediaLoaderObj = world.eid2obj.get(eid)!; transformPosition.fromArray(NetworkedTransform.position[eid]); if (mediaLoaderObj.position.near(transformPosition, 0.001)) { @@ -417,7 +417,7 @@ export function mediaLoadingSystem(world: HubsWorld) { mediaLoadedEnterQuery(world).forEach(() => APP.scene?.emit("listed_media_changed")); mediaLoadedExitQuery(world).forEach(() => APP.scene?.emit("listed_media_changed")); - mediaRefreshEnterQuery(world).forEach((eid: EntityID) => { + mediaRefreshEnterQuery(world).forEach(eid => { if (!jobs.has(eid)) { jobs.add(eid, clearRollbacks => refreshMedia(world, eid, clearRollbacks)); } diff --git a/src/bit-systems/object-menu.ts b/src/bit-systems/object-menu.ts index e7545c9936..51c6702a73 100644 --- a/src/bit-systems/object-menu.ts +++ b/src/bit-systems/object-menu.ts @@ -105,7 +105,7 @@ function startRotation(world: HubsWorld, menuEid: EntityID, targetEid: EntityID) } const transformSystem = APP.scene!.systems["transform-selected-object"]; const physicsSystem = AFRAME.scenes[0].systems["hubs-systems"].physicsSystem; - physicsSystem.updateRigidBody(Rigidbody.bodyId[targetEid], { type: "kinematic" }); + physicsSystem.updateRigidBodyOptions(Rigidbody.bodyId[targetEid], { type: "kinematic" }); const rightCursorEid = anyEntityWith(world, RemoteRight)!; transformSystem.startTransform(world.eid2obj.get(targetEid)!, world.eid2obj.get(rightCursorEid)!, { mode: TRANSFORM_MODE.CURSOR @@ -137,7 +137,7 @@ function startScaling(world: HubsWorld, menuEid: EntityID, targetEid: EntityID) // TODO: Remove the dependency with AFRAME const transformSystem = (AFRAME as any).scenes[0].systems["transform-selected-object"]; const physicsSystem = AFRAME.scenes[0].systems["hubs-systems"].physicsSystem; - physicsSystem.updateRigidBody(Rigidbody.bodyId[targetEid], { type: "kinematic" }); + physicsSystem.updateRigidBodyOptions(Rigidbody.bodyId[targetEid], { type: "kinematic" }); const rightCursorEid = anyEntityWith(world, RemoteRight)!; scalingHandler = new ScalingHandler(world.eid2obj.get(targetEid), transformSystem); scalingHandler!.objectToScale = world.eid2obj.get(targetEid); diff --git a/src/bit-systems/scene-loading.ts b/src/bit-systems/scene-loading.ts index 5f5a176d91..c782c001b6 100644 --- a/src/bit-systems/scene-loading.ts +++ b/src/bit-systems/scene-loading.ts @@ -7,6 +7,7 @@ import { HeightFieldTag, NavMesh, Networked, + PhysicsShape, SceneLoader, ScenePreviewCamera, SceneRoot, diff --git a/src/components/body-helper.js b/src/components/body-helper.js index 96496da1e0..e7b17d63d7 100644 --- a/src/components/body-helper.js +++ b/src/components/body-helper.js @@ -1,7 +1,6 @@ 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; @@ -42,7 +41,6 @@ AFRAME.registerComponent("body-helper", { 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 }, diff --git a/src/components/media-loader.js b/src/components/media-loader.js index 94961d74f6..9c89bbddcf 100644 --- a/src/components/media-loader.js +++ b/src/components/media-loader.js @@ -284,10 +284,8 @@ AFRAME.registerComponent("media-loader", { // TODO this does duplicate work in some cases, but finish() is the only consistent place to do it const contentBounds = getBox(this.el.object3D, this.el.getObject3D("mesh")).getSize(new THREE.Vector3()); - if (el.eid) { - addComponent(APP.world, MediaContentBounds, el.eid); - MediaContentBounds.bounds[el.eid].set(contentBounds.toArray()); - } + addComponent(APP.world, MediaContentBounds, el.eid); + MediaContentBounds.bounds[el.eid].set(contentBounds.toArray()); el.emit("media-loaded"); }; diff --git a/src/constants.ts b/src/constants.ts index cded600d34..64c1c988e7 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -11,7 +11,7 @@ export enum COLLISION_LAYERS { DEFAULT_INTERACTABLE = INTERACTABLES | ENVIRONMENT | AVATAR | HANDS | MEDIA_FRAMES, UNOWNED_INTERACTABLE = INTERACTABLES | HANDS | MEDIA_FRAMES, DEFAULT_SPAWNER = INTERACTABLES | HANDS -} +}; export enum AAModes { NONE = "NONE", diff --git a/src/inflators/media-frame.js b/src/inflators/media-frame.js index d1dccaaace..84db6250ef 100644 --- a/src/inflators/media-frame.js +++ b/src/inflators/media-frame.js @@ -15,28 +15,14 @@ export const AxisAlignType = { }; export const MEDIA_FRAME_FLAGS = { - SCALE_TO_BOUNDS: 1 << 0, - ACTIVE: 1 << 1, - SNAP_TO_CENTER: 1 << 2, - LOCKED: 1 << 3 -}; - -export const MediaTypes = { - all: MediaType.ALL, - "all-2d": MediaType.ALL_2D, - model: MediaType.MODEL, - image: MediaType.IMAGE, - video: MediaType.VIDEO, - pdf: MediaType.PDF + SCALE_TO_BOUNDS: 1 << 0 }; const DEFAULTS = { bounds: { x: 1, y: 1, z: 1 }, mediaType: "all", scaleToBounds: true, - align: { x: "center", y: "center", z: "center" }, - active: true, - locked: false + align: { x: "center", y: "center", z: "center" } }; export function inflateMediaFrame(world, eid, componentProps) { componentProps = Object.assign({}, DEFAULTS, componentProps); @@ -82,16 +68,17 @@ export function inflateMediaFrame(world, eid, componentProps) { addComponent(world, MediaFrame, eid, true); addComponent(world, NetworkedMediaFrame, eid, true); - NetworkedMediaFrame.flags[eid] |= MEDIA_FRAME_FLAGS.ACTIVE; - if (componentProps.snapToCenter) { - NetworkedMediaFrame.flags[eid] |= MEDIA_FRAME_FLAGS.SNAP_TO_CENTER; - } - if (!hasComponent(world, Networked, eid)) addComponent(world, Networked, eid); // Media types accepted - MediaFrame.mediaType[eid] = MediaTypes[componentProps.mediaType]; - NetworkedMediaFrame.mediaType[eid] = MediaFrame.mediaType[eid]; + MediaFrame.mediaType[eid] = { + all: MediaType.ALL, + "all-2d": MediaType.ALL_2D, + model: MediaType.MODEL, + image: MediaType.IMAGE, + video: MediaType.VIDEO, + pdf: MediaType.PDF + }[componentProps.mediaType]; // Bounds MediaFrame.bounds[eid].set([componentProps.bounds.x, componentProps.bounds.y, componentProps.bounds.z]); // Axis alignment @@ -114,15 +101,6 @@ export function inflateMediaFrame(world, eid, componentProps) { if (componentProps.scaleToBounds) flags |= MEDIA_FRAME_FLAGS.SCALE_TO_BOUNDS; MediaFrame.flags[eid] = flags; - if (componentProps.active) { - NetworkedMediaFrame.flags[eid] |= MEDIA_FRAME_FLAGS.ACTIVE; - MediaFrame.flags[eid] |= MEDIA_FRAME_FLAGS.ACTIVE; - } - if (componentProps.locked) { - NetworkedMediaFrame.flags[eid] |= MEDIA_FRAME_FLAGS.LOCKED; - MediaFrame.flags[eid] |= MEDIA_FRAME_FLAGS.LOCKED; - } - inflateRigidBody(world, eid, { type: Type.KINEMATIC, collisionGroup: COLLISION_LAYERS.MEDIA_FRAMES, diff --git a/src/inflators/model.tsx b/src/inflators/model.tsx index cad41dc33b..42875bd551 100644 --- a/src/inflators/model.tsx +++ b/src/inflators/model.tsx @@ -14,7 +14,15 @@ function camelCase(s: string) { export type ModelParams = { model: Object3D }; // These components are all handled in some special way, not through inflators -const ignoredComponents = ["visible", "frustum", "frustrum", "shadow", "animation-mixer", "loop-animation"]; +const ignoredComponents = [ + "visible", + "frustum", + "frustrum", + "shadow", + "networked", + "animation-mixer", + "loop-animation" +]; function inflateComponents( world: HubsWorld, diff --git a/src/inflators/rigid-body.ts b/src/inflators/rigid-body.ts index d68f2d664c..54f2cf55e5 100644 --- a/src/inflators/rigid-body.ts +++ b/src/inflators/rigid-body.ts @@ -1,8 +1,7 @@ import { addComponent } from "bitecs"; -import { NetworkedRigidBody, Rigidbody } from "../bit-components"; +import { Rigidbody } from "../bit-components"; import { HubsWorld } from "../app"; import { CONSTANTS } from "three-ammo"; -import { COLLISION_LAYERS } from "../constants"; export enum Type { STATIC = 0, @@ -10,12 +9,6 @@ export enum Type { KINEMATIC } -export enum CollisionGroup { - OBJECTS = "objects", - ENVIRONMENT = "environment", - AVATARS = "avatars" -} - export enum ActivationState { ACTIVE_TAG = 0, ISLAND_SLEEPING = 1, @@ -24,23 +17,6 @@ export enum ActivationState { DISABLE_SIMULATION = 4 } -export type BodyParams = { - type: string; - mass: number; - gravity: { x: number; y: number; z: number }; - linearDamping: number; - angularDamping: number; - linearSleepingThreshold: number; - angularSleepingThreshold: number; - angularFactor: { x: number; y: number; z: number }; - activationState: string; - emitCollisionEvents: boolean; - disableCollision: boolean; - collisionFilterGroup: number; - collisionFilterMask: number; - scaleAutoUpdate: boolean; -}; - export type RigidBodyParams = { type: Type; mass: number; @@ -85,50 +61,10 @@ export const getTypeString = (eid: number) => { return Object.values(CONSTANTS.TYPE)[Rigidbody.type[eid]]; }; -export const getStringFromActivationState = (eid: number) => { +export const getActivationStateString = (eid: number) => { return Object.values(CONSTANTS.ACTIVATION_STATE)[Rigidbody.activationState[eid]]; }; -export const getActivationStateFromString = (activationState: string) => { - switch (activationState) { - case CONSTANTS.ACTIVATION_STATE.ACTIVE_TAG: - return ActivationState.ACTIVE_TAG; - case CONSTANTS.ACTIVATION_STATE.DISABLE_DEACTIVATION: - return ActivationState.DISABLE_DEACTIVATION; - case CONSTANTS.ACTIVATION_STATE.DISABLE_SIMULATION: - return ActivationState.DISABLE_SIMULATION; - case CONSTANTS.ACTIVATION_STATE.ISLAND_SLEEPING: - return ActivationState.ISLAND_SLEEPING; - case CONSTANTS.ACTIVATION_STATE.WANTS_DEACTIVATION: - return ActivationState.WANTS_DEACTIVATION; - } - return ActivationState.ACTIVE_TAG; -}; - -export const getTypeFromBodyType = (type: string) => { - switch (type) { - case "static": - return Type.STATIC; - case "dynamic": - return Type.DYNAMIC; - case "kinematic": - return Type.KINEMATIC; - } - return Type.KINEMATIC; -}; - -export const getBodyTypeFromType = (type: Type) => { - switch (type) { - case Type.STATIC: - return "static"; - case Type.DYNAMIC: - return "dynamic"; - case Type.KINEMATIC: - return "kinematic"; - } - return "kinematic"; -}; - export const getBodyFromRigidBody = (eid: number) => { return { mass: Rigidbody.mass[eid], @@ -142,154 +78,44 @@ export const getBodyFromRigidBody = (eid: number) => { y: Rigidbody.angularFactor[eid][1], z: Rigidbody.angularFactor[eid][2] }, - activationState: getStringFromActivationState(eid), - emitCollisionEvents: (Rigidbody.flags[eid] & RIGID_BODY_FLAGS.EMIT_COLLISION_EVENTS) !== 0, - scaleAutoUpdate: (Rigidbody.flags[eid] & RIGID_BODY_FLAGS.SCALE_AUTO_UPDATE) !== 0, + activationState: getActivationStateString(eid), + emitCollisionEvents: Rigidbody.flags[eid] & RIGID_BODY_FLAGS.EMIT_COLLISION_EVENTS, + scaleAutoUpdate: Rigidbody.flags[eid] & RIGID_BODY_FLAGS.SCALE_AUTO_UPDATE, type: getTypeString(eid), - disableCollision: (Rigidbody.flags[eid] & RIGID_BODY_FLAGS.DISABLE_COLLISION) !== 0, + disableCollision: Rigidbody.flags[eid] & RIGID_BODY_FLAGS.DISABLE_COLLISION, collisionFilterGroup: Rigidbody.collisionFilterGroup[eid], collisionFilterMask: Rigidbody.collisionFilterMask[eid] }; }; -export const updateBodyParams = (eid: number, params: Partial) => { - const currentParams = getBodyFromRigidBody(eid); - const bodyParams = Object.assign({}, currentParams, params) as BodyParams; - - Rigidbody.type[eid] = getTypeFromBodyType(bodyParams.type); - Rigidbody.mass[eid] = bodyParams.mass; - Rigidbody.gravity[eid].set([bodyParams.gravity.x, bodyParams.gravity.y, bodyParams.gravity.z]); - Rigidbody.linearDamping[eid] = bodyParams.linearDamping; - Rigidbody.angularDamping[eid] = bodyParams.angularDamping; - Rigidbody.linearSleepingThreshold[eid] = bodyParams.linearSleepingThreshold; - Rigidbody.angularSleepingThreshold[eid] = bodyParams.angularSleepingThreshold; - Rigidbody.angularFactor[eid].set([ - bodyParams.angularFactor.x, - bodyParams.angularFactor.y, - bodyParams.angularFactor.z - ]); - Rigidbody.activationState[eid] = getActivationStateFromString(params.activationState!); - bodyParams.emitCollisionEvents && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.EMIT_COLLISION_EVENTS); - bodyParams.disableCollision && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.DISABLE_COLLISION); - Rigidbody.collisionFilterGroup[eid] = bodyParams.collisionFilterGroup; - Rigidbody.collisionFilterMask[eid] = bodyParams.collisionFilterMask; - bodyParams.scaleAutoUpdate && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.SCALE_AUTO_UPDATE); +const updateRigidBody = (eid: number, params: RigidBodyParams) => { + Rigidbody.type[eid] = params.type; + Rigidbody.mass[eid] = params.mass; + Rigidbody.gravity[eid].set(params.gravity); + Rigidbody.linearDamping[eid] = params.linearDamping; + Rigidbody.angularDamping[eid] = params.angularDamping; + Rigidbody.linearSleepingThreshold[eid] = params.linearSleepingThreshold; + Rigidbody.angularSleepingThreshold[eid] = params.angularSleepingThreshold; + Rigidbody.angularFactor[eid].set(params.angularFactor); + Rigidbody.activationState[eid] = params.activationState; + params.emitCollisionEvents && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.EMIT_COLLISION_EVENTS); + params.disableCollision && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.DISABLE_COLLISION); + Rigidbody.collisionFilterGroup[eid] = params.collisionGroup; + Rigidbody.collisionFilterMask[eid] = params.collisionMask; + params.scaleAutoUpdate && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.SCALE_AUTO_UPDATE); }; -export const updateRigidBodyParams = (eid: number, params: Partial) => { - if (params.type !== undefined) { - Rigidbody.type[eid] = params.type; - } - if (params.mass !== undefined) { - Rigidbody.mass[eid] = params.mass; - } - if (params.gravity !== undefined) { - Rigidbody.gravity[eid].set(params.gravity); - } - if (params.linearDamping !== undefined) { - Rigidbody.linearDamping[eid] = params.linearDamping; - } - if (params.angularDamping !== undefined) { - Rigidbody.angularDamping[eid] = params.angularDamping; - } - if (params.linearSleepingThreshold !== undefined) { - Rigidbody.linearSleepingThreshold[eid] = params.linearSleepingThreshold; - } - if (params.angularSleepingThreshold !== undefined) { - Rigidbody.angularSleepingThreshold[eid] = params.angularSleepingThreshold; - } - if (params.angularFactor !== undefined) { - Rigidbody.angularFactor[eid].set(params.angularFactor); - } - if (params.activationState !== undefined) { - Rigidbody.activationState[eid] = params.activationState; - } - if (params.emitCollisionEvents !== undefined) { - Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.EMIT_COLLISION_EVENTS; - } - if (params.disableCollision !== undefined) { - Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.DISABLE_COLLISION; - } - if (params.scaleAutoUpdate !== undefined) { - Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.SCALE_AUTO_UPDATE; - } - if (params.collisionGroup !== undefined) { - Rigidbody.collisionFilterGroup[eid] = params.collisionGroup; - } - if (params.collisionMask !== undefined) { - Rigidbody.collisionFilterMask[eid] = params.collisionMask; - } +export const updateRigiBodyParams = (eid: number, params: Partial) => { + const currentParams = getBodyFromRigidBody(eid); + const bodyParams = Object.assign({}, currentParams, params); + updateRigidBody(eid, bodyParams); }; export function inflateRigidBody(world: HubsWorld, eid: number, params: Partial) { - const bodyParams = Object.assign({}, DEFAULTS, params) as RigidBodyParams; + const bodyParams = Object.assign({}, DEFAULTS, params); addComponent(world, Rigidbody, eid); - addComponent(world, NetworkedRigidBody, eid); - - Rigidbody.type[eid] = bodyParams.type; - Rigidbody.mass[eid] = bodyParams.mass; - Rigidbody.gravity[eid].set(bodyParams.gravity); - Rigidbody.linearDamping[eid] = bodyParams.linearDamping; - Rigidbody.angularDamping[eid] = bodyParams.angularDamping; - Rigidbody.linearSleepingThreshold[eid] = bodyParams.linearSleepingThreshold; - Rigidbody.angularSleepingThreshold[eid] = bodyParams.angularSleepingThreshold; - Rigidbody.angularFactor[eid].set(bodyParams.angularFactor); - Rigidbody.activationState[eid] = bodyParams.activationState; - bodyParams.emitCollisionEvents && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.EMIT_COLLISION_EVENTS); - bodyParams.disableCollision && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.DISABLE_COLLISION); - Rigidbody.collisionFilterGroup[eid] = bodyParams.collisionGroup; - Rigidbody.collisionFilterMask[eid] = bodyParams.collisionMask; - Rigidbody.initialCollisionFilterMask[eid] = bodyParams.collisionMask; - bodyParams.scaleAutoUpdate && (Rigidbody.flags[eid] |= RIGID_BODY_FLAGS.SCALE_AUTO_UPDATE); - NetworkedRigidBody.prevType[eid] = bodyParams.type; - - return eid; -} - -export enum GLTFRigidBodyType { - STATIC = "static", - DYNAMIC = "dynamic", - KINEMATIC = "kinematic" -} - -export enum GLTFRigidBodyCollisionGroup { - OBJECTS = "objects", - ENVIRONMENT = "environment", - AVATARS = "avatars", - MEDIA_FRAMES = "media-frames" -} - -const GLTF_DEFAULTS = { - ...DEFAULTS, - type: GLTFRigidBodyType.DYNAMIC, - collisionGroup: GLTFRigidBodyCollisionGroup.OBJECTS, - collisionMask: [GLTFRigidBodyCollisionGroup.AVATARS] -}; - -const gltfGroupToLayer = { - [GLTFRigidBodyCollisionGroup.OBJECTS]: COLLISION_LAYERS.INTERACTABLES, - [GLTFRigidBodyCollisionGroup.ENVIRONMENT]: COLLISION_LAYERS.ENVIRONMENT, - [GLTFRigidBodyCollisionGroup.AVATARS]: COLLISION_LAYERS.AVATAR, - [GLTFRigidBodyCollisionGroup.MEDIA_FRAMES]: COLLISION_LAYERS.MEDIA_FRAMES -} as const; - -export interface GLTFRigidBodyParams - extends Partial> { - type?: GLTFRigidBodyType; - collisionGroup?: GLTFRigidBodyCollisionGroup; - collisionMask?: GLTFRigidBodyCollisionGroup[]; -} - -export function inflateGLTFRigidBody(world: HubsWorld, eid: number, params: GLTFRigidBodyParams) { - const bodyParams = Object.assign({}, GLTF_DEFAULTS, params); - - inflateRigidBody(world, eid, { - ...bodyParams, - type: Object.values(GLTFRigidBodyType).indexOf(bodyParams.type), - collisionGroup: gltfGroupToLayer[bodyParams.collisionGroup], - collisionMask: bodyParams.collisionMask.reduce((acc, m) => acc | gltfGroupToLayer[m], 0) - }); + updateRigidBody(eid, bodyParams); return eid; } diff --git a/src/inflators/spawner.ts b/src/inflators/spawner.ts index 1587fadb39..78c6be0310 100644 --- a/src/inflators/spawner.ts +++ b/src/inflators/spawner.ts @@ -42,6 +42,7 @@ export function inflateSpawner(world: HubsWorld, eid: number, props: SpawnerPara inflateRigidBody(world, eid, { mass: 0, + type: Type.STATIC, collisionGroup: COLLISION_LAYERS.INTERACTABLES, collisionMask: COLLISION_LAYERS.DEFAULT_SPAWNER }); diff --git a/src/react-components/room/RoomSidebar.js b/src/react-components/room/RoomSidebar.js index f722075a8b..98438a0b1c 100644 --- a/src/react-components/room/RoomSidebar.js +++ b/src/react-components/room/RoomSidebar.js @@ -70,12 +70,12 @@ function SceneAttribution({ attribution }) { } SceneAttribution.propTypes = { - attribution: PropTypes.shape({ + attribution: { name: PropTypes.string, title: PropTypes.string, author: PropTypes.string, url: PropTypes.string - }) + } }; // To assist with content control, we avoid displaying scene links to users who are not the scene diff --git a/src/systems/bit-constraints-system.js b/src/systems/bit-constraints-system.js index d75ed8a7b1..1fa79aea1a 100644 --- a/src/systems/bit-constraints-system.js +++ b/src/systems/bit-constraints-system.js @@ -19,10 +19,8 @@ import { ConstraintHandLeft, ConstraintHandRight, ConstraintRemoteLeft, - ConstraintRemoteRight, - NetworkedRigidBody + ConstraintRemoteRight } from "../bit-components"; -import { Type, getBodyFromRigidBody, getBodyTypeFromType } from "../inflators/rigid-body"; const queryRemoteRight = defineQuery([HeldRemoteRight, OffersRemoteConstraint]); const queryEnterRemoteRight = enterQuery(queryRemoteRight); @@ -47,7 +45,7 @@ function add(world, physicsSystem, interactor, constraintComponent, entities) { for (let i = 0; i < entities.length; i++) { const eid = findAncestorEntity(world, entities[i], ancestor => hasComponent(world, Rigidbody, ancestor)); if (!entityExists(world, eid)) continue; - physicsSystem.updateRigidBody(eid, grabBodyOptions); + physicsSystem.updateRigidBodyOptions(eid, grabBodyOptions); physicsSystem.addConstraint(interactor, Rigidbody.bodyId[eid], Rigidbody.bodyId[interactor], {}); addComponent(world, Constraint, eid); addComponent(world, constraintComponent, eid); @@ -59,16 +57,8 @@ function remove(world, offersConstraint, constraintComponent, physicsSystem, int const eid = findAncestorEntity(world, entities[i], ancestor => hasComponent(world, Rigidbody, ancestor)); if (!entityExists(world, eid)) continue; if (hasComponent(world, offersConstraint, entities[i]) && hasComponent(world, Rigidbody, eid)) { - physicsSystem.updateRigidBody(eid, { - type: getBodyTypeFromType(NetworkedRigidBody.prevType[eid]), - ...releaseBodyOptions - }); + physicsSystem.updateRigidBodyOptions(eid, releaseBodyOptions); physicsSystem.removeConstraint(interactor); - if (Rigidbody.type[eid] === Type.DYNAMIC) { - physicsSystem.activateBody(Rigidbody.bodyId[eid]); - // This shouldn't be necessary but for some reason it doesn't activate the body if we don't update the body afterwards - physicsSystem.updateRigidBody(eid, getBodyFromRigidBody(eid)); - } removeComponent(world, constraintComponent, eid); if ( !hasComponent(world, ConstraintHandLeft, eid) && diff --git a/src/systems/bit-media-frames.js b/src/systems/bit-media-frames.js index d264bc52a9..f56ed3ad79 100644 --- a/src/systems/bit-media-frames.js +++ b/src/systems/bit-media-frames.js @@ -19,13 +19,13 @@ import { MediaContentBounds, MediaFrame, MediaImage, + MediaLoaded, MediaPDF, MediaVideo, Networked, NetworkedMediaFrame, Owned, - Rigidbody, - Holdable + Rigidbody } from "../bit-components"; import { MediaType } from "../utils/media-utils"; import { cloneObject3D, disposeNode, setMatrixWorld } from "../utils/three-utils"; @@ -36,13 +36,12 @@ import { addObject3DComponent } from "../utils/jsx-entity"; import { updateMaterials } from "../utils/material-utils"; import { MEDIA_FRAME_FLAGS, AxisAlignType } from "../inflators/media-frame"; import { Matrix4, NormalBlending, Quaternion, RGBAFormat, Vector3 } from "three"; -import { COLLISION_LAYERS } from "../constants"; const EMPTY_COLOR = 0x6fc0fd; const HOVER_COLOR = 0x2f80ed; const FULL_COLOR = 0x808080; -const mediaFramesQuery = defineQuery([MediaFrame, NetworkedMediaFrame]); +const mediaFramesQuery = defineQuery([MediaFrame]); const enteredMediaFramesQuery = enterQuery(mediaFramesQuery); const exitedMediaFramesQuery = exitQuery(mediaFramesQuery); @@ -55,19 +54,11 @@ function mediaTypeMaskFor(world, eid) { mediaTypeMask |= el.components["media-image"] && MediaType.IMAGE; mediaTypeMask |= el.components["media-pdf"] && MediaType.PDF; } else { - const rigidBody = findAncestorWithComponent(world, Rigidbody, eid); - if (rigidBody && Rigidbody.collisionFilterMask[rigidBody] & COLLISION_LAYERS.MEDIA_FRAMES) { - const interactable = findChildWithComponent(world, Holdable, eid); - if (interactable) { - mediaTypeMask |= hasComponent(world, GLTFModel, interactable) && MediaType.MODEL; - mediaTypeMask |= hasComponent(world, MediaVideo, interactable) && MediaType.VIDEO; - mediaTypeMask |= hasComponent(world, MediaImage, interactable) && MediaType.IMAGE; - mediaTypeMask |= hasComponent(world, MediaPDF, interactable) && MediaType.PDF; - if (mediaTypeMask === 0) { - mediaTypeMask |= MediaType.MODEL; - } - } - } + const mediaEid = findChildWithComponent(world, MediaLoaded, eid); + mediaTypeMask |= hasComponent(world, GLTFModel, mediaEid) && MediaType.MODEL; + mediaTypeMask |= hasComponent(world, MediaVideo, mediaEid) && MediaType.VIDEO; + mediaTypeMask |= hasComponent(world, MediaImage, mediaEid) && MediaType.IMAGE; + mediaTypeMask |= hasComponent(world, MediaPDF, mediaEid) && MediaType.PDF; } return mediaTypeMask; } @@ -331,7 +322,7 @@ export function mediaFramesSystem(world, physicsSystem) { if (capturedEid && isCapturedOwned && !isCapturedHeld && !isFrameDeleting && isCapturedColliding) { snapToFrame(world, frame, capturedEid); - physicsSystem.updateRigidBody(capturedEid, { type: "kinematic" }); + physicsSystem.updateRigidBodyOptions(capturedEid, { type: "kinematic" }); } else if ( (isFrameOwned && MediaFrame.capturedNid[frame] && world.deletedNids.has(MediaFrame.capturedNid[frame])) || (capturedEid && isCapturedOwned && !isCapturedColliding) || @@ -362,7 +353,7 @@ export function mediaFramesSystem(world, physicsSystem) { obj.updateMatrices(); tmpVec3.setFromMatrixScale(obj.matrixWorld).toArray(NetworkedMediaFrame.scale[frame]); snapToFrame(world, frame, capturable); - physicsSystem.updateRigidBody(capturable, { type: "kinematic" }); + physicsSystem.updateRigidBodyOptions(capturable, { type: "kinematic" }); } } @@ -375,7 +366,7 @@ export function mediaFramesSystem(world, physicsSystem) { // TODO: If you are resetting scale because you lost a race for the frame, // you should probably also move the object away from the frame. setMatrixScale(world.eid2obj.get(capturedEid), MediaFrame.scale[frame]); - physicsSystem.updateRigidBody(capturedEid, { type: "dynamic" }); + physicsSystem.updateRigidBodyOptions(capturedEid, { type: "dynamic" }); } MediaFrame.capturedNid[frame] = NetworkedMediaFrame.capturedNid[frame]; diff --git a/src/systems/bit-physics.ts b/src/systems/bit-physics.ts index d9b891d2c4..a07c325956 100644 --- a/src/systems/bit-physics.ts +++ b/src/systems/bit-physics.ts @@ -1,12 +1,10 @@ import { defineQuery, enterQuery, entityExists, exitQuery, hasComponent, Not } from "bitecs"; -import { Object3DTag, Rigidbody, PhysicsShape, AEntity, TextTag } from "../bit-components"; +import { Object3DTag, Rigidbody, PhysicsShape, AEntity } from "../bit-components"; import { getShapeFromPhysicsShape } from "../inflators/physics-shape"; -import { findAncestorWithComponent, hasAnyComponent } from "../utils/bit-utils"; +import { findAncestorWithComponent } from "../utils/bit-utils"; import { getBodyFromRigidBody } from "../inflators/rigid-body"; import { HubsWorld } from "../app"; import { PhysicsSystem } from "./physics-system"; -import { EntityID } from "../utils/networking-types"; -import { Object3D } from "three"; const rigidbodyQuery = defineQuery([Rigidbody, Object3DTag, Not(AEntity)]); const rigidbodyEnteredQuery = enterQuery(rigidbodyQuery); @@ -15,49 +13,23 @@ const shapeQuery = defineQuery([PhysicsShape]); const shapeEnterQuery = enterQuery(shapeQuery); const shapeExitQuery = exitQuery(shapeQuery); -// We don't want to add physics shape for some child entities -// ie. If the object already has a physics shape we don't want to create another one. -// If the object has a text component, we don't want to create a physics shape for it. -const NO_PHYSICS_COMPONENTS = [Rigidbody, TextTag]; - function addPhysicsShapes(world: HubsWorld, physicsSystem: PhysicsSystem, eid: number) { const bodyId = PhysicsShape.bodyId[eid]; const obj = world.eid2obj.get(eid)!; - - // Avoid adding physics shapes for child entities with specific components. - if (obj) { - const hidden = new Map(); - obj.traverse((child: Object3D) => { - if (child.eid! !== eid && hasAnyComponent(world, NO_PHYSICS_COMPONENTS, child.eid!)) { - hidden.set(child.eid!, child.parent!.eid!); - } - }); - for (let child of hidden.keys()) { - const childObj = world.eid2obj.get(child)!; - childObj.removeFromParent(); - } - - const shape = getShapeFromPhysicsShape(eid); - const shapeId = physicsSystem.addShapes(bodyId, obj, shape); - PhysicsShape.shapeId[eid] = shapeId; - - hidden.forEach((parent: EntityID, child: EntityID) => { - const parentObj = world.eid2obj.get(parent)!; - const childObj = world.eid2obj.get(child)!; - parentObj.add(childObj); - }); - } + const shape = getShapeFromPhysicsShape(eid); + const shapeId = physicsSystem.addShapes(bodyId, obj, shape); + PhysicsShape.shapeId[eid] = shapeId; } export const physicsCompatSystem = (world: HubsWorld, physicsSystem: PhysicsSystem) => { - rigidbodyEnteredQuery(world).forEach((eid: EntityID) => { + rigidbodyEnteredQuery(world).forEach(eid => { const obj = world.eid2obj.get(eid); const body = getBodyFromRigidBody(eid); const bodyId = physicsSystem.addBody(obj, body); Rigidbody.bodyId[eid] = bodyId; }); - shapeEnterQuery(world).forEach((eid: EntityID) => { + shapeEnterQuery(world).forEach(eid => { const bodyEid = findAncestorWithComponent(world, Rigidbody, eid); if (bodyEid) { PhysicsShape.bodyId[eid] = Rigidbody.bodyId[bodyEid]; @@ -67,11 +39,9 @@ export const physicsCompatSystem = (world: HubsWorld, physicsSystem: PhysicsSyst } }); - shapeExitQuery(world).forEach((eid: EntityID) => - physicsSystem.removeShapes(PhysicsShape.bodyId[eid], PhysicsShape.shapeId[eid]) - ); + shapeExitQuery(world).forEach(eid => physicsSystem.removeShapes(PhysicsShape.bodyId[eid], PhysicsShape.shapeId[eid])); - rigidbodyExitedQuery(world).forEach((eid: EntityID) => { + rigidbodyExitedQuery(world).forEach(eid => { if (entityExists(world, eid) && hasComponent(world, PhysicsShape, eid)) { physicsSystem.removeShapes(PhysicsShape.bodyId[eid], PhysicsShape.shapeId[eid]); // The PhysicsShape is still on this entity! diff --git a/src/systems/floaty-object-system.js b/src/systems/floaty-object-system.js index 24fd720ae5..f857fa8e70 100644 --- a/src/systems/floaty-object-system.js +++ b/src/systems/floaty-object-system.js @@ -53,7 +53,7 @@ function makeKinematicOnRelease(world) { const physicsSystem = AFRAME.scenes[0].systems["hubs-systems"].physicsSystem; makeKinematicOnReleaseExitQuery(world).forEach(eid => { if (!entityExists(world, eid) || !hasComponent(world, Owned, eid)) return; - physicsSystem.updateRigidBody(eid, { type: "kinematic" }); + physicsSystem.updateRigidBodyOptions(eid, { type: "kinematic" }); }); } @@ -73,14 +73,14 @@ export const floatyObjectSystem = world => { const physicsSystem = AFRAME.scenes[0].systems["hubs-systems"].physicsSystem; enteredFloatyObjectsQuery(world).forEach(eid => { - physicsSystem.updateRigidBody(eid, { + physicsSystem.updateRigidBodyOptions(eid, { type: "kinematic", gravity: { x: 0, y: 0, z: 0 } }); }); enterHeldFloatyObjectsQuery(world).forEach(eid => { - physicsSystem.updateRigidBody(eid, { + physicsSystem.updateRigidBodyOptions(eid, { gravity: { x: 0, y: 0, z: 0 }, type: "dynamic", collisionFilterMask: COLLISION_LAYERS.HANDS | COLLISION_LAYERS.MEDIA_FRAMES @@ -95,7 +95,7 @@ export const floatyObjectSystem = world => { const bodyData = physicsSystem.bodyUuidToData.get(bodyId); if (FloatyObject.flags[eid] & FLOATY_OBJECT_FLAGS.MODIFY_GRAVITY_ON_RELEASE) { if (bodyData.linearVelocity < 1.85) { - physicsSystem.updateRigidBody(eid, { + physicsSystem.updateRigidBodyOptions(eid, { gravity: { x: 0, y: 0, z: 0 }, angularDamping: FloatyObject.flags[eid] & FLOATY_OBJECT_FLAGS.REDUCE_ANGULAR_FLOAT ? 0.89 : 0.5, linearDamping: 0.95, @@ -105,7 +105,7 @@ export const floatyObjectSystem = world => { }); addComponent(world, MakeStaticWhenAtRest, eid); } else { - physicsSystem.updateRigidBody(eid, { + physicsSystem.updateRigidBodyOptions(eid, { gravity: { x: 0, y: FloatyObject.releaseGravity[eid], z: 0 }, angularDamping: 0.01, linearDamping: 0.01, @@ -131,7 +131,7 @@ export const floatyObjectSystem = world => { const angle = Math.random() * Math.PI * 2; const x = Math.cos(angle); const z = Math.sin(angle); - physicsSystem.updateRigidBody(eid, { + physicsSystem.updateRigidBodyOptions(eid, { gravity: { x, y: force, z }, angularDamping: 0.01, linearDamping: 0.01, @@ -142,7 +142,7 @@ export const floatyObjectSystem = world => { removeComponent(world, MakeStaticWhenAtRest, eid); } } else { - physicsSystem.updateRigidBody(eid, { + physicsSystem.updateRigidBodyOptions(eid, { collisionFilterMask: COLLISION_LAYERS.DEFAULT_INTERACTABLE, gravity: { x: 0, y: -9.8, z: 0 } }); diff --git a/src/systems/hold-system.js b/src/systems/hold-system.js index 6c2c1abd37..72316e506a 100644 --- a/src/systems/hold-system.js +++ b/src/systems/hold-system.js @@ -13,7 +13,8 @@ import { HeldHandLeft, AEntity, Networked, - Rigidbody + MediaLoader, + Deletable } from "../bit-components"; import { canMove } from "../utils/permissions-utils"; import { canMove as canMoveEntity } from "../utils/bit-permissions-utils"; @@ -74,15 +75,12 @@ export function isAEntityPinned(world, eid) { // Alternate solution: Simply recognize an entity as pinned if its any // ancestor is pinned (in hold-system) unless there is a case that // descendant entity under pinned entity wants to be grabbable. -// -// Update: As now we are supporting grabbable scene objects, we look for the -// root holdable entity with a rigid body as the only rigid body -// in the hierarchy should be at the root of the grabbable object. function grab(world, userinput, queryHovered, held, grabPath) { const hovered = queryHovered(world)[0]; - const interactable = findAncestorWithComponents(world, [Holdable, Rigidbody], hovered); - const target = interactable ? interactable : hovered; + // Special path for Dropped/Pasted Media with new loader enabled. Check the comment above. + const mediaRoot = findAncestorWithComponents(world, [Deletable, MediaLoader, Holdable], hovered); + const target = mediaRoot ? mediaRoot : hovered; const isEntityPinned = isPinned(target) || isAEntityPinned(world, target); if ( diff --git a/src/systems/hubs-systems.ts b/src/systems/hubs-systems.ts index e656237cd3..96a6e8c86f 100644 --- a/src/systems/hubs-systems.ts +++ b/src/systems/hubs-systems.ts @@ -93,7 +93,6 @@ import { linkedPDFSystem } from "../bit-systems/linked-pdf-system"; import { inspectSystem } from "../bit-systems/inspect-system"; import { snapMediaSystem } from "../bit-systems/snap-media-system"; import { scaleWhenGrabbedSystem } from "../bit-systems/scale-when-grabbed-system"; -import { interactableSystem } from "../bit-systems/interactable-system"; declare global { interface Window { @@ -241,7 +240,6 @@ export function mainTick(xrFrame: XRFrame, renderer: WebGLRenderer, scene: Scene hubsSystems.hoverMenuSystem.tick(); hubsSystems.positionAtBorderSystem.tick(); hubsSystems.twoPointStretchingSystem.tick(); - interactableSystem(world); hubsSystems.holdableButtonSystem.tick(); hubsSystems.hoverButtonSystem.tick(); diff --git a/src/systems/networked-transform.js b/src/systems/networked-transform.js index 81ab689a6c..9a501c25d7 100644 --- a/src/systems/networked-transform.js +++ b/src/systems/networked-transform.js @@ -1,24 +1,12 @@ -import { addComponent, defineQuery, hasComponent, enterQuery } from "bitecs"; -import { LinearRotate, LinearScale, LinearTranslate, NetworkedTransform, Owned, Networked } from "../bit-components"; +import { addComponent, defineQuery, hasComponent } from "bitecs"; +import { LinearRotate, LinearScale, LinearTranslate, NetworkedTransform, Owned } from "../bit-components"; import { millisecondsBetweenTicks } from "../bit-systems/networking"; const query = defineQuery([NetworkedTransform]); const tmpVec = new THREE.Vector3(); const tmpQuat = new THREE.Quaternion(); - -const networkedTransformEnterQuery = enterQuery(query); export function networkedTransformSystem(world) { - networkedTransformEnterQuery(world).forEach(eid => { - // If it's a scene object that has not been owned yet, - // we initialize its networked transform to the initial object transform. - if (Networked.creator[eid] === APP.getSid("scene") && Networked.owner[eid] === APP.getSid("reticulum")) { - const obj = world.eid2obj.get(eid); - NetworkedTransform.position[eid].set(obj.position.toArray()); - NetworkedTransform.rotation[eid].set(obj.quaternion.toArray()); - NetworkedTransform.scale[eid].set(obj.scale.toArray()); - } - }); const ents = query(world); for (let i = 0; i < ents.length; i++) { const eid = ents[i]; diff --git a/src/systems/on-ownership-lost.js b/src/systems/on-ownership-lost.js index e392265ebf..ae055891c6 100644 --- a/src/systems/on-ownership-lost.js +++ b/src/systems/on-ownership-lost.js @@ -1,3 +1,4 @@ +import { COLLISION_LAYERS } from "../constants"; import { exitQuery, defineQuery, removeComponent, hasComponent, entityExists } from "bitecs"; import { Held, @@ -12,6 +13,7 @@ import { // TODO this seems wrong, nothing sets it back unless its a floaty object const exitOwned = exitQuery(defineQuery([Owned])); const componentsToRemove = [Held, HeldHandRight, HeldHandLeft, HeldRemoteRight, HeldRemoteLeft]; +const kinematicOptions = { type: "kinematic", collisionFilterMask: COLLISION_LAYERS.UNOWNED_INTERACTABLE }; export function onOwnershipLost(world) { const physicsSystem = AFRAME.scenes[0].systems["hubs-systems"].physicsSystem; @@ -25,10 +27,7 @@ export function onOwnershipLost(world) { } if (hasComponent(world, Rigidbody, eid)) { - physicsSystem.updateRigidBody(eid, { - type: "kinematic", - collisionFilterMask: Rigidbody.initialCollisionFilterMask[eid] - }); + physicsSystem.updateRigidBodyOptions(eid, kinematicOptions); } } } diff --git a/src/systems/physics-system.js b/src/systems/physics-system.js index 20e92fcc06..1489cafad9 100644 --- a/src/systems/physics-system.js +++ b/src/systems/physics-system.js @@ -3,7 +3,7 @@ import { AmmoDebugConstants, DefaultBufferSize } from "ammo-debug-drawer"; import configs from "../utils/configs"; import ammoWasmUrl from "ammo.js/builds/ammo.wasm.wasm"; import { Rigidbody } from "../bit-components"; -import { updateBodyParams } from "../inflators/rigid-body"; +import { updateRigiBodyParams } from "../inflators/rigid-body"; const MESSAGE_TYPES = CONSTANTS.MESSAGE_TYPES, TYPE = CONSTANTS.TYPE, @@ -231,7 +231,6 @@ export class PhysicsSystem { const bodyId = this.nextBodyUuid; this.nextBodyUuid += 1; - object3D.updateMatrices(); this.workerHelpers.addBody(bodyId, object3D, options); this.bodyUuidToData.set(bodyId, { @@ -251,7 +250,7 @@ export class PhysicsSystem { updateRigidBody(eid, options) { const bodyId = Rigidbody.bodyId[eid]; - updateBodyParams(eid, options); + updateRigiBodyParams(eid, options); if (this.bodyUuidToData.has(bodyId)) { this.bodyUuidToData.get(bodyId).options = options; this.workerHelpers.updateBody(bodyId, options); @@ -260,6 +259,18 @@ export class PhysicsSystem { } } + updateRigidBodyOptions(eid, options) { + const bodyId = Rigidbody.bodyId[eid]; + updateRigiBodyParams(eid, options); + const bodyData = this.bodyUuidToData.get(bodyId); + if (!bodyData) { + // TODO: Fix me. + console.warn("updateBodyOptions called for invalid bodyId"); + return; + } + this.workerHelpers.updateBody(bodyId, Object.assign(this.bodyUuidToData.get(bodyId).options, options)); + } + removeBody(uuid) { const bodyData = this.bodyUuidToData.get(uuid); if (!bodyData) { @@ -274,10 +285,8 @@ export class PhysicsSystem { if (bodyData.isInitialized) { delete this.indexToUuid[bodyData.index]; bodyData.collisions.forEach(otherId => { - const collisions = this.bodyUuidToData.get(otherId)?.collisions; - // This can happen when removing multiple bodies in a frame - if (!collisions) return; - collisions.splice(collisions.indexOf(uuid), 1); + const otherData = this.bodyUuidToData.get(otherId).collisions; + otherData.splice(otherData.indexOf(uuid), 1); }); this.bodyUuids.splice(this.bodyUuids.indexOf(uuid), 1); this.bodyUuidToData.delete(uuid); diff --git a/src/utils/bit-utils.ts b/src/utils/bit-utils.ts index bfc954b308..009fb52882 100644 --- a/src/utils/bit-utils.ts +++ b/src/utils/bit-utils.ts @@ -25,15 +25,8 @@ export function hasAnyComponent(world: HubsWorld, components: Component[], eid: return false; } -export function findAncestorEntity( - world: HubsWorld, - eid: number, - predicate: (eid: number, world: HubsWorld) => boolean -) { - const obj = findAncestor( - world.eid2obj.get(eid)!, - (o: Object3D) => !!(o.eid && predicate(o.eid, world)) - ) as Object3D | null; +export function findAncestorEntity(world: HubsWorld, eid: number, predicate: (eid: number) => boolean) { + const obj = findAncestor(world.eid2obj.get(eid)!, (o: Object3D) => !!(o.eid && predicate(o.eid))) as Object3D | null; return obj && obj.eid!; } @@ -43,7 +36,7 @@ export function findAncestorEntities(world: HubsWorld, eid: number, predicate: ( } export function findAncestorWithComponent(world: HubsWorld, component: Component, eid: number) { - return findAncestorEntity(world, eid, (otherId, world) => hasComponent(world, component, otherId)); + return findAncestorEntity(world, eid, otherId => hasComponent(world, component, otherId)); } export function findAncestorsWithComponent(world: HubsWorld, component: Component, eid: number): EntityID[] { diff --git a/src/utils/jsx-entity.ts b/src/utils/jsx-entity.ts index 8273eef3c9..15e9e9c9f8 100644 --- a/src/utils/jsx-entity.ts +++ b/src/utils/jsx-entity.ts @@ -70,6 +70,7 @@ import { inflateSpawnpoint, inflateWaypoint, WaypointParams } from "../inflators import { inflateReflectionProbe, ReflectionProbeParams } from "../inflators/reflection-probe"; import { HubsWorld } from "../app"; import { Group, Material, Object3D, Texture } from "three"; +import { AlphaMode } from "./create-image-mesh"; import { MediaLoaderParams } from "../inflators/media-loader"; import { preload } from "./preload"; import { DirectionalLightParams, inflateDirectionalLight } from "../inflators/directional-light"; @@ -77,6 +78,7 @@ import { AmbientLightParams, inflateAmbientLight } from "../inflators/ambient-li import { HemisphereLightParams, inflateHemisphereLight } from "../inflators/hemisphere-light"; import { PointLightParams, inflatePointLight } from "../inflators/point-light"; import { SpotLightParams, inflateSpotLight } from "../inflators/spot-light"; +import { ProjectionMode } from "./projection-mode"; import { inflateSkybox, SkyboxParams } from "../inflators/skybox"; import { inflateSpawner, SpawnerParams } from "../inflators/spawner"; import { inflateVideoTextureTarget, VideoTextureTargetParams } from "../inflators/video-texture-target"; @@ -91,12 +93,13 @@ import { inflateAudioParams } from "../inflators/audio-params"; import { AudioSourceParams, inflateAudioSource } from "../inflators/audio-source"; import { AudioTargetParams, inflateAudioTarget } from "../inflators/audio-target"; import { PhysicsShapeParams, inflatePhysicsShape } from "../inflators/physics-shape"; -import { inflateGLTFRigidBody, inflateRigidBody, RigidBodyParams } from "../inflators/rigid-body"; +import { inflateRigidBody, RigidBodyParams } from "../inflators/rigid-body"; import { AmmoShapeParams, inflateAmmoShape } from "../inflators/ammo-shape"; import { BoxColliderParams, inflateBoxCollider } from "../inflators/box-collider"; import { inflateTrimesh } from "../inflators/trimesh"; import { HeightFieldParams, inflateHeightField } from "../inflators/heightfield"; import { inflateAudioSettings } from "../inflators/audio-settings"; +import { HubsVideoTexture } from "../textures/HubsVideoTexture"; import { inflateMediaLink, MediaLinkParams } from "../inflators/media-link"; import { inflateObjectMenuTarget, ObjectMenuTargetParams } from "../inflators/object-menu-target"; import { inflateObjectMenuTransform, ObjectMenuTransformParams } from "../inflators/object-menu-transform"; @@ -255,15 +258,13 @@ export interface ComponentData { hemisphereLight?: HemisphereLightParams; pointLight?: PointLightParams; spotLight?: SpotLightParams; + grabbable?: GrabbableParams; billboard?: { onlyY: boolean }; mirror?: MirrorParams; audioZone?: AudioZoneParams; audioParams?: AudioSettings; mediaFrame?: any; text?: TextParams; - networked?: any; - networkedTransform?: any; - grabbable?: GrabbableParams; } type OptionalParams = Partial | true; @@ -308,6 +309,7 @@ export interface JSXComponentData extends ComponentData { quack?: true; // @TODO Define all the anys + networked?: any; textButton?: any; hoverButton?: any; hoverableVisuals?: any; @@ -315,6 +317,7 @@ export interface JSXComponentData extends ComponentData { physicsShape?: OptionalParams; floatyObject?: any; networkedFloatyObject?: any; + networkedTransform?: any; objectMenu?: { backgroundRef: Ref; pinButtonRef: Ref; @@ -396,10 +399,6 @@ export interface GLTFComponentData extends ComponentData { audioTarget: AudioTargetParams; audioSettings: SceneAudioSettings; mediaLink: MediaLinkParams; - rigidbody?: OptionalParams; - // TODO GLTFPhysicsShapeParams - physicsShape?: AmmoShapeParams; - grabbable?: GrabbableParams; // deprecated spawnPoint?: true; @@ -430,6 +429,7 @@ declare global { } export const commonInflators: Required<{ [K in keyof ComponentData]: InflatorFn }> = { + grabbable: inflateGrabbable, billboard: createDefaultInflator(Billboard), // inflators that create Object3Ds @@ -442,10 +442,7 @@ export const commonInflators: Required<{ [K in keyof ComponentData]: InflatorFn audioZone: inflateAudioZone, audioParams: inflateAudioParams, mediaFrame: inflateMediaFrame, - text: inflateText, - networkedTransform: createDefaultInflator(NetworkedTransform), - networked: createDefaultInflator(Networked), - grabbable: inflateGrabbable + text: inflateText }; const jsxInflators: Required<{ [K in keyof JSXComponentData]: InflatorFn }> = { @@ -469,6 +466,8 @@ const jsxInflators: Required<{ [K in keyof JSXComponentData]: InflatorFn }> = { networkedFloatyObject: createDefaultInflator(NetworkedFloatyObject), makeKinematicOnRelease: createDefaultInflator(MakeKinematicOnRelease), destroyAtExtremeDistance: createDefaultInflator(DestroyAtExtremeDistance), + networkedTransform: createDefaultInflator(NetworkedTransform), + networked: createDefaultInflator(Networked), objectMenu: createDefaultInflator(ObjectMenu), mirrorMenu: createDefaultInflator(MirrorMenu), followInFov: inflateFollowInFov, @@ -534,9 +533,7 @@ export const gltfInflators: Required<{ [K in keyof GLTFComponentData]: InflatorF trimesh: inflateTrimesh, heightfield: inflateHeightField, audioSettings: inflateAudioSettings, - mediaLink: inflateMediaLink, - rigidbody: inflateGLTFRigidBody, - physicsShape: inflateAmmoShape + mediaLink: inflateMediaLink }; function jsxInflatorExists(name: string): name is keyof JSXComponentData { diff --git a/src/utils/network-schemas.ts b/src/utils/network-schemas.ts index 86637b4dbf..b97517af7e 100644 --- a/src/utils/network-schemas.ts +++ b/src/utils/network-schemas.ts @@ -5,7 +5,6 @@ import { NetworkedFloatyObject, NetworkedMediaFrame, NetworkedPDF, - NetworkedRigidBody, NetworkedTransform, NetworkedVideo, NetworkedWaypoint @@ -17,7 +16,6 @@ import { NetworkedTransformSchema } from "./networked-transform-schema"; import { NetworkedVideoSchema } from "./networked-video-schema"; import { NetworkedWaypointSchema } from "./networked-waypoint-schema"; import type { CursorBuffer, EntityID } from "./networking-types"; -import { NetworkedRigidBodySchema } from "./networked-rigid-body"; export interface StoredComponent { version: number; @@ -48,7 +46,6 @@ schemas.set(NetworkedFloatyObject, { ...defineNetworkSchema(NetworkedFloatyObject) }); schemas.set(NetworkedPDF, NetworkedPDFSchema); -schemas.set(NetworkedRigidBody, NetworkedRigidBodySchema); export const networkableComponents = Array.from(schemas.keys()); diff --git a/src/utils/networked-media-frame-schema.ts b/src/utils/networked-media-frame-schema.ts index 19cd816dc6..175b022af6 100644 --- a/src/utils/networked-media-frame-schema.ts +++ b/src/utils/networked-media-frame-schema.ts @@ -8,30 +8,16 @@ const runtimeSerde = defineNetworkSchema(NetworkedMediaFrame); const migrations = new Map(); migrations.set(0, ({ data }: StoredComponent) => { - return { version: 2, data }; + return { version: 1, data }; }); function apply(eid: EntityID, { version, data }: StoredComponent) { - if (version === 1) { - const { capturedNid, scale }: { capturedNid: string; scale: ArrayVec3 } = data; - write(NetworkedMediaFrame.capturedNid, eid, capturedNid); - write(NetworkedMediaFrame.scale, eid, scale); - write(NetworkedMediaFrame.flags, eid, 0); - return true; - } else if (version === 2) { - const { - capturedNid, - scale, - flags, - mediaType - }: { capturedNid: string; scale: ArrayVec3; flags: number; mediaType: number } = data; - write(NetworkedMediaFrame.capturedNid, eid, capturedNid); - write(NetworkedMediaFrame.scale, eid, scale); - write(NetworkedMediaFrame.flags, eid, flags); - write(NetworkedMediaFrame.mediaType, eid, mediaType); - return true; - } - return false; + if (version !== 1) return false; + + const { capturedNid, scale }: { capturedNid: string; scale: ArrayVec3 } = data; + write(NetworkedMediaFrame.capturedNid, eid, capturedNid); + write(NetworkedMediaFrame.scale, eid, scale); + return true; } export const NetworkedMediaFrameSchema: NetworkSchema = { @@ -40,12 +26,10 @@ export const NetworkedMediaFrameSchema: NetworkSchema = { deserialize: runtimeSerde.deserialize, serializeForStorage: function serializeForStorage(eid: EntityID) { return { - version: 2, + version: 1, data: { capturedNid: read(NetworkedMediaFrame.capturedNid, eid), - scale: read(NetworkedMediaFrame.scale, eid), - flags: read(NetworkedMediaFrame.flags, eid), - mediaType: read(NetworkedMediaFrame.mediaType, eid) + scale: read(NetworkedMediaFrame.scale, eid) } }; }, diff --git a/src/utils/networked-rigid-body.ts b/src/utils/networked-rigid-body.ts deleted file mode 100644 index 41b9cf0aaa..0000000000 --- a/src/utils/networked-rigid-body.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { NetworkedRigidBody } from "../bit-components"; -import { defineNetworkSchema } from "./define-network-schema"; -import { deserializerWithMigrations, Migration, NetworkSchema, read, StoredComponent, write } from "./network-schemas"; -import type { EntityID } from "./networking-types"; - -const runtimeSerde = defineNetworkSchema(NetworkedRigidBody); - -const migrations = new Map(); - -function apply(eid: EntityID, { version, data }: StoredComponent) { - if (version !== 1) return false; - - const { prevType }: { prevType: number } = data; - write(NetworkedRigidBody.prevType, eid, prevType); - return true; -} - -export const NetworkedRigidBodySchema: NetworkSchema = { - componentName: "networked-rigid-body", - serialize: runtimeSerde.serialize, - deserialize: runtimeSerde.deserialize, - serializeForStorage: function serializeForStorage(eid: EntityID) { - return { - version: 1, - data: { - prevType: read(NetworkedRigidBody.prevType, eid) - } - }; - }, - deserializeFromStorage: deserializerWithMigrations(migrations, apply) -};