diff --git a/src/bit-systems/object-menu-transform-system.ts b/src/bit-systems/object-menu-transform-system.ts index b2f06feaa4..a82a727bc9 100644 --- a/src/bit-systems/object-menu-transform-system.ts +++ b/src/bit-systems/object-menu-transform-system.ts @@ -1,4 +1,4 @@ -import { defineQuery } from "bitecs"; +import { defineQuery, removeComponent } from "bitecs"; import { HubsWorld } from "../app"; import { ObjectMenuTarget, ObjectMenuTransform } from "../bit-components"; import { EntityID } from "../utils/networking-types"; @@ -7,7 +7,6 @@ import { isFacingCamera, setFromObject, setMatrixWorld } from "../utils/three-ut import { ObjectMenuTargetFlags } from "../inflators/object-menu-target"; import { ObjectMenuTransformFlags } from "../inflators/object-menu-transform"; -const offset = new Vector3(); const tmpVec1 = new Vector3(); const tmpVec2 = new Vector3(); const tmpQuat1 = new Quaternion(); @@ -45,18 +44,6 @@ function transformMenu(world: HubsWorld, menu: EntityID) { if (!targetObj || !enabled) return; const menuObj = world.eid2obj.get(menu)!; - - // Calculate the menu offset based on visible elements - const center = (ObjectMenuTransform.flags[menu] & ObjectMenuTransformFlags.Center) !== 0 ? true : false; - if (center && ObjectMenuTransform.targetObjectRef[menu] !== ObjectMenuTransform.prevObjectRef[menu]) { - getAABB(menuObj, aabb); - aabb.getCenter(tmpVec1); - getAABB(menuObj, aabb, true); - aabb.getCenter(tmpVec2); - offset.subVectors(tmpVec1, tmpVec2); - offset.z = 0; - } - const camera = APP.scene?.systems["hubs-systems"].cameraSystem.viewingCamera; camera.updateMatrices(); @@ -75,11 +62,6 @@ function transformMenu(world: HubsWorld, menu: EntityID) { menuObj.lookAt(tmpVec2.setFromMatrixPosition(camera.matrixWorld)); menuObj.translateZ(sphere.radius); - if (center) { - menuObj.position.add(offset); - menuObj.matrixNeedsUpdate = true; - } - // TODO We need to handle the menu positioning when the player is inside the bounding sphere. // For now we are defaulting to the current AFrame behavior. } else { @@ -102,11 +84,6 @@ function transformMenu(world: HubsWorld, menu: EntityID) { tmpMat4.multiply(tmpMat42); } - if (center) { - tmpMat42.makeTranslation(offset.x, offset.y, offset.z); - tmpMat4.multiply(tmpMat42); - } - setMatrixWorld(menuObj, tmpMat4); } ObjectMenuTransform.prevObjectRef[menu] = ObjectMenuTransform.targetObjectRef[menu]; diff --git a/src/bit-systems/object-menu.ts b/src/bit-systems/object-menu.ts index adc20f7ab4..0b181e8835 100644 --- a/src/bit-systems/object-menu.ts +++ b/src/bit-systems/object-menu.ts @@ -46,6 +46,7 @@ import { ObjectMenuTransformFlags } from "../inflators/object-menu-transform"; import { COLLISION_LAYERS } from "../constants"; import { FLOATY_OBJECT_FLAGS } from "../systems/floaty-object-system"; import { INSPECTABLE_FLAGS } from "./inspect-system"; +import { ObjectMenuPositions } from "../prefabs/object-menu"; // Working variables. const _vec3_1 = new Vector3(); const _vec3_2 = new Vector3(); @@ -282,26 +283,62 @@ function updateVisibility(world: HubsWorld, menu: EntityID, frozen: boolean) { const media = MediaLoader.mediaRef[target]; const isVideoImagePdf = hasAnyComponent(world, [MediaVideo, MediaImage, MediaPDF], media); const isMirrored = hasComponent(world, MediaMirrored, target); + const isDropped = hasComponent(world, ObjectDropped, target); const isInspectable = hasComponent(world, Inspectable, target); const isInspected = hasComponent(world, Inspected, target); const isRefreshing = hasComponent(world, MediaRefresh, target); - // Parent visibility doesn't block raycasting, so we must set each button to be invisible - // TODO: Ensure that children of invisible entities aren't raycastable - world.eid2obj.get(ObjectMenu.unpinButtonRef[menu])!.visible = visible && isEntityPinned && canIPin; - world.eid2obj.get(ObjectMenu.pinButtonRef[menu])!.visible = visible && !isEntityPinned && canIPin; - world.eid2obj.get(ObjectMenu.removeButtonRef[menu])!.visible = visible && !isEntityPinned && canISpawnMove; - world.eid2obj.get(ObjectMenu.cloneButtonRef[menu])!.visible = visible && canISpawnMove; - world.eid2obj.get(ObjectMenu.rotateButtonRef[menu])!.visible = - visible && (!isEntityPinned || canIPin) && canISpawnMove; - world.eid2obj.get(ObjectMenu.scaleButtonRef[menu])!.visible = - visible && (!isEntityPinned || canIPin) && canISpawnMove; - world.eid2obj.get(ObjectMenu.openLinkButtonRef[menu])!.visible = visible; - world.eid2obj.get(ObjectMenu.dropButtonRef[menu])!.visible = - !isVideoImagePdf && !isEntityPinned && !hasComponent(world, ObjectDropped, target); - world.eid2obj.get(ObjectMenu.mirrorButtonRef[menu])!.visible = isVideoImagePdf && !isMirrored; - world.eid2obj.get(ObjectMenu.inspectButtonRef[menu])!.visible = isVideoImagePdf && isInspectable && !isInspected; - world.eid2obj.get(ObjectMenu.refreshButtonRef[menu])!.visible = visible && canIPin && canISpawnMove && !isRefreshing; + const openLinkButtonObj = world.eid2obj.get(ObjectMenu.openLinkButtonRef[menu])!; + const mirrorButtonObj = world.eid2obj.get(ObjectMenu.mirrorButtonRef[menu])!; + const inspectButtonObj = world.eid2obj.get(ObjectMenu.inspectButtonRef[menu])!; + const refreshButtonObj = world.eid2obj.get(ObjectMenu.refreshButtonRef[menu])!; + + openLinkButtonObj.visible = visible; + mirrorButtonObj.visible = visible && isVideoImagePdf && !isMirrored; + inspectButtonObj.visible = visible && isInspectable && !isInspected; + refreshButtonObj.visible = visible && !isRefreshing; + + if (canISpawnMove) { + world.eid2obj.get(ObjectMenu.unpinButtonRef[menu])!.visible = visible && isEntityPinned && canIPin; + world.eid2obj.get(ObjectMenu.pinButtonRef[menu])!.visible = visible && !isEntityPinned && canIPin; + world.eid2obj.get(ObjectMenu.removeButtonRef[menu])!.visible = visible && !isEntityPinned; + world.eid2obj.get(ObjectMenu.cloneButtonRef[menu])!.visible = visible; + world.eid2obj.get(ObjectMenu.rotateButtonRef[menu])!.visible = visible && (!isEntityPinned || canIPin); + world.eid2obj.get(ObjectMenu.scaleButtonRef[menu])!.visible = visible && (!isEntityPinned || canIPin); + world.eid2obj.get(ObjectMenu.dropButtonRef[menu])!.visible = + visible && !isVideoImagePdf && !isEntityPinned && !isDropped; + + openLinkButtonObj.position.fromArray(ObjectMenuPositions.openLink); + mirrorButtonObj.position.fromArray(ObjectMenuPositions.mirror); + if (isEntityPinned) { + inspectButtonObj.position.fromArray(ObjectMenuPositions.inspectP); + } else { + inspectButtonObj.position.fromArray(ObjectMenuPositions.inspect); + } + refreshButtonObj.position.fromArray(ObjectMenuPositions.refresh); + } else { + [ + ObjectMenu.unpinButtonRef[menu], + ObjectMenu.pinButtonRef[menu], + ObjectMenu.removeButtonRef[menu], + ObjectMenu.cloneButtonRef[menu], + ObjectMenu.rotateButtonRef[menu], + ObjectMenu.scaleButtonRef[menu], + ObjectMenu.dropButtonRef[menu] + ].forEach(ref => { + world.eid2obj.get(ref)!.visible = false; + }); + + openLinkButtonObj.position.fromArray(ObjectMenuPositions.openLinkU); + mirrorButtonObj.position.fromArray(ObjectMenuPositions.mirrorU); + inspectButtonObj.position.fromArray(ObjectMenuPositions.inspectU); + refreshButtonObj.position.fromArray(ObjectMenuPositions.refreshU); + } + + openLinkButtonObj.matrixNeedsUpdate = true; + mirrorButtonObj.matrixNeedsUpdate = true; + inspectButtonObj.matrixNeedsUpdate = true; + refreshButtonObj.matrixNeedsUpdate = true; // This is a hacky way of giving a chance to the object-menu-transform system to center the menu based on the // visible buttons without accounting for the background plane. diff --git a/src/inflators/object-menu-transform.ts b/src/inflators/object-menu-transform.ts index 7f8cb3c099..ccb31f667a 100644 --- a/src/inflators/object-menu-transform.ts +++ b/src/inflators/object-menu-transform.ts @@ -5,8 +5,7 @@ import { ObjectMenuTransform } from "../bit-components"; export const ObjectMenuTransformFlags = { Enabled: 1 << 0, - Center: 1 << 1, - Scale: 1 << 2 + Scale: 1 << 1 }; export type ObjectMenuTransformParams = { @@ -21,9 +20,6 @@ const DEFAULTS = { export function inflateObjectMenuTransform(world: HubsWorld, eid: EntityID, params: ObjectMenuTransformParams) { params = Object.assign({}, DEFAULTS, params); addComponent(world, ObjectMenuTransform, eid); - if (params.center === true) { - ObjectMenuTransform.flags[eid] |= ObjectMenuTransformFlags.Center; - } if (params.scale === true) { ObjectMenuTransform.flags[eid] |= ObjectMenuTransformFlags.Scale; } diff --git a/src/prefabs/object-menu.tsx b/src/prefabs/object-menu.tsx index 1198f51fbd..eb1dcc4ec1 100644 --- a/src/prefabs/object-menu.tsx +++ b/src/prefabs/object-menu.tsx @@ -123,6 +123,7 @@ function InspectButton(props: Attrs) { height={buttonHeight} type={BUTTON_TYPES.DEFAULT} holdable + holdableButton icon={{ texture, cacheKey, scale: [0.165, 0.165, 0.165] }} {...props} /> @@ -195,6 +196,7 @@ function RotateButton(props: Attrs) { height={buttonHeight} type={BUTTON_TYPES.ACTION} holdable + holdableButton icon={{ texture, cacheKey, scale: [0.165, 0.165, 0.165] }} {...props} /> @@ -226,6 +228,7 @@ function ScaleButton(props: Attrs) { height={buttonHeight} type={BUTTON_TYPES.ACTION} holdable + holdableButton icon={{ texture, cacheKey, scale: [0.165, 0.165, 0.165] }} {...props} /> @@ -233,22 +236,27 @@ function ScaleButton(props: Attrs) { } // prettier-ignore -const position = { +export const ObjectMenuPositions = { background: [ 0, 0, uiZ - 0.0005] as ArrayVec3, - pin: [ 0, 0.125, uiZ] as ArrayVec3, - unpin: [ 0, 0.125, uiZ] as ArrayVec3, - focus: [-0.25, 0.375, uiZ] as ArrayVec3, - track: [ 0.25, 0.375, uiZ] as ArrayVec3, - remove: [ 0, -0.275, uiZ] as ArrayVec3, - drop: [ 0, -0.425, uiZ] as ArrayVec3, - inspect: [ 0, -0.425, uiZ] as ArrayVec3, - deserializeDrawing: [ -0.3, -0.625, uiZ] as ArrayVec3, - openLink: [ 0.25, -0.275, uiZ] as ArrayVec3, - refresh: [ 0.25, -0.425, uiZ] as ArrayVec3, - clone: [-0.25, -0.275, uiZ] as ArrayVec3, - rotate: [ -0.2, -0.125, uiZ] as ArrayVec3, - mirror: [ 0, -0.125, uiZ] as ArrayVec3, - scale: [ 0.2, -0.125, uiZ] as ArrayVec3, + pin: [ 0, 0.225, uiZ] as ArrayVec3, + unpin: [ 0, 0.225, uiZ] as ArrayVec3, + focus: [-0.25, 0.575, uiZ] as ArrayVec3, + track: [ 0.25, 0.575, uiZ] as ArrayVec3, + remove: [ 0, -0.075, uiZ] as ArrayVec3, + drop: [ 0, -0.225, uiZ] as ArrayVec3, + inspect: [ 0, -0.225, uiZ] as ArrayVec3, + inspectU: [ 0, 0.075, uiZ] as ArrayVec3, + inspectP: [ 0, -0.075, uiZ] as ArrayVec3, + deserializeDrawing: [ -0.3, -0.425, uiZ] as ArrayVec3, + openLink: [ 0.25, -0.075, uiZ] as ArrayVec3, + openLinkU: [ 0, -0.075, uiZ] as ArrayVec3, + refresh: [ 0.25, -0.225, uiZ] as ArrayVec3, + refreshU: [ 0, -0.225, uiZ] as ArrayVec3, + clone: [-0.25, -0.075, uiZ] as ArrayVec3, + rotate: [ -0.2, 0.075, uiZ] as ArrayVec3, + mirror: [ 0, 0.075, uiZ] as ArrayVec3, + mirrorU: [ 0, 0.225, uiZ] as ArrayVec3, + scale: [ 0.2, 0.075, uiZ] as ArrayVec3, }; export function ObjectMenuPrefab() { @@ -273,7 +281,7 @@ export function ObjectMenuPrefab() { return ( - - - - - - - - - - - - - - + + + + + + + + + + + + + + ); } - -// ui interactable-ui -// layers mask 768 -// withPermission: spawn_and_move_media - -// pinButtonTip: Pinning will broadcast this object to Discord. - -// sprite camera-action.png -// cameraFocusLabel focus - -// sprite camera-action.png -// cameraTrackLabel track - -// sprite remove-action.png -// - -// visibility on content types: -// "contentTypes: video/ audio/ image/ application/vnd.apple.mpegurl application/x-mpegurl application/pdf; visible: false;" -// sprite drop-action.png -// hide-when-pinned-and-forbidden - -// holdable -// sprite focus-action.png -// visibility-on-content-types="contentTypes: video/ audio/ image/ application/vnd.apple.mpegurl application/x-mpegurl application/pdf;" - -// sprite deserialize-action.png -// class="deserialize-drawing" : lookup what else is using this - -// text: open link - -// text: refresh - -// text: clone - -// sprite: rotate-action.png -// hide-when-pinned-and-forbidden - -// sprite: inspect-action.png -// visibility-on-content-types="contentTypes: video/ audio/ image/ application/vnd.apple.mpegurl application/x-mpegurl application/pdf;" - -// sprite: scale-action.png -// hide-when-pinned-and-forbidden - -// unprivileged menu... -// refreshButton -// openLinkButton -// mirrorMediaButton -// inspectButton diff --git a/src/prefabs/pdf-menu.tsx b/src/prefabs/pdf-menu.tsx index 6b87d72573..ef2f1da72b 100644 --- a/src/prefabs/pdf-menu.tsx +++ b/src/prefabs/pdf-menu.tsx @@ -61,7 +61,7 @@ export function PDFMenuPrefab() { return (