Skip to content

Commit

Permalink
Merge pull request #6442 from mozilla/bitecs-drop-button
Browse files Browse the repository at this point in the history
BitECS drop button
  • Loading branch information
keianhzo authored Jan 22, 2024
2 parents 3509ac8 + a303043 commit 8ac0b72
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/bit-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ export const ObjectMenu = defineComponent({
handlingTargetRef: Types.eid,
flags: Types.ui8
});
export const ObjectDropped = defineComponent();
// TODO: Store this data elsewhere, since only one or two will ever exist.
export const LinkHoverMenu = defineComponent({
targetObjectRef: Types.eid,
Expand Down
47 changes: 42 additions & 5 deletions src/bit-systems/object-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,20 @@ import {
Rigidbody,
Deleting,
Deletable,
MediaLoader
MediaLoader,
ObjectDropped,
FloatyObject,
Owned,
MediaVideo,
MediaImage,
MediaPDF
} from "../bit-components";
import { anyEntityWith, findAncestorWithComponent, findAncestorWithComponents } from "../utils/bit-utils";
import {
anyEntityWith,
findAncestorWithComponent,
findAncestorWithComponents,
hasAnyComponent
} from "../utils/bit-utils";
import { createNetworkedEntity } from "../utils/create-networked-entity";
import HubChannel from "../utils/hub-channel";
import type { EntityID } from "../utils/networking-types";
Expand All @@ -28,7 +39,8 @@ import { TRANSFORM_MODE } from "../components/transform-object-button";
import { ScalingHandler } from "../components/scale-button";
import { canPin, setPinned } from "../utils/bit-pinning-helper";
import { ObjectMenuTransformFlags } from "../inflators/object-menu-transform";

import { COLLISION_LAYERS } from "../constants";
import { FLOATY_OBJECT_FLAGS } from "../systems/floaty-object-system";
// Working variables.
const _vec3_1 = new Vector3();
const _vec3_2 = new Vector3();
Expand Down Expand Up @@ -178,7 +190,7 @@ function handleClicks(world: HubsWorld, menu: EntityID, hubChannel: HubChannel)
ObjectMenu.flags[menu] &= ~ObjectMenuFlags.Visible;
deleteTheDeletableAncestor(world, ObjectMenu.targetRef[menu]);
} else if (clicked(world, ObjectMenu.dropButtonRef[menu])) {
console.log("Clicked drop");
addComponent(world, ObjectDropped, ObjectMenu.targetRef[menu]);
} else if (clicked(world, ObjectMenu.inspectButtonRef[menu])) {
console.log("Clicked inspect");
} else if (clicked(world, ObjectMenu.deserializeDrawingButtonRef[menu])) {
Expand Down Expand Up @@ -247,6 +259,8 @@ function updateVisibility(world: HubsWorld, menu: EntityID, frozen: boolean) {
const canISpawnMove = APP.hubChannel.can("spawn_and_move_media");
const canIPin = !!(target && canPin(APP.hubChannel, target));
const isEntityPinned = isPinned(target);
const media = MediaLoader.mediaRef[target];
const isVideoImagePdf = hasAnyComponent(world, [MediaVideo, MediaImage, MediaPDF], media);

// 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
Expand All @@ -259,6 +273,8 @@ function updateVisibility(world: HubsWorld, menu: EntityID, frozen: boolean) {
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);

// 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.
Expand All @@ -272,14 +288,15 @@ function updateVisibility(world: HubsWorld, menu: EntityID, frozen: boolean) {
world.eid2obj.get(ObjectMenu.deserializeDrawingButtonRef[menu])!.visible = false;
world.eid2obj.get(ObjectMenu.mirrorButtonRef[menu])!.visible = false;
world.eid2obj.get(ObjectMenu.inspectButtonRef[menu])!.visible = false;
world.eid2obj.get(ObjectMenu.dropButtonRef[menu])!.visible = false;
world.eid2obj.get(ObjectMenu.refreshButtonRef[menu])!.visible = false;
}

const hoveredQuery = defineQuery([HoveredRemoteRight]);
const heldQuery = defineQuery([HeldRemoteRight]);
const heldEnterQuery = enterQuery(heldQuery);
const heldExitQuery = exitQuery(heldQuery);
const objectDroppedQuery = defineQuery([ObjectDropped]);
const objectDroppedEnterQuery = enterQuery(objectDroppedQuery);
export function objectMenuSystem(world: HubsWorld, sceneIsFrozen: boolean, hubChannel: HubChannel) {
const menu = anyEntityWith(world, ObjectMenu)!;

Expand All @@ -301,5 +318,25 @@ export function objectMenuSystem(world: HubsWorld, sceneIsFrozen: boolean, hubCh
scalingHandler.tick();
}
}

objectDroppedEnterQuery(world).forEach(eid => {
takeOwnership(world, eid);
if (!hasComponent(world, Owned, eid)) return;

const physicsSystem = APP.scene?.systems["hubs-systems"].physicsSystem;
FloatyObject.flags[eid] &= ~FLOATY_OBJECT_FLAGS.MODIFY_GRAVITY_ON_RELEASE;
physicsSystem.updateRigidBody(eid, {
type: "dynamic",
gravity: { x: 0, y: -9.8, z: 0 },
angularDamping: 0.01,
linearDamping: 0.01,
linearSleepingThreshold: 1.6,
angularSleepingThreshold: 2.5,
collisionFilterMask: COLLISION_LAYERS.DEFAULT_INTERACTABLE
});

physicsSystem.activateBody(Rigidbody.bodyId[eid]);
});

updateVisibility(world, menu, sceneIsFrozen);
}
11 changes: 7 additions & 4 deletions src/prefabs/object-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Button3D, BUTTON_TYPES } from "./button3D";
import rotateIconSrc from "../assets/rotate-action.png";
import scaleIconSrc from "../assets/scale-action.png";
import removeIconSrc from "../assets/remove-action.png";
import dropIconSrc from "../assets/drop-action.png";
import { Plane } from "./plane";
import { FrontSide } from "three";
import { Layers } from "../camera-layers";
Expand All @@ -13,7 +14,8 @@ export async function loadObjectMenuButtonIcons() {
return Promise.all([
loadTexture(rotateIconSrc, 1, "image/png"),
loadTexture(scaleIconSrc, 1, "image/png"),
loadTexture(removeIconSrc, 1, "image/png")
loadTexture(removeIconSrc, 1, "image/png"),
loadTexture(dropIconSrc, 1, "image/png")
]);
}

Expand Down Expand Up @@ -93,14 +95,15 @@ function RemoveButton(props: Attrs) {
}

function DropButton(props: Attrs) {
const { texture, cacheKey } = loadTextureFromCache(dropIconSrc, 1);
return (
<Button3D
name="Drop Button"
scale={buttonScale}
width={0.4}
width={buttonHeight}
height={buttonHeight}
type={BUTTON_TYPES.DEFAULT}
text={"drop"}
icon={{ texture, cacheKey, scale: [0.165, 0.165, 0.165] }}
{...props}
/>
);
Expand Down Expand Up @@ -230,7 +233,7 @@ const position = {
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.1, -0.625, uiZ] as ArrayVec3,
drop: [ 0, -0.425, uiZ] as ArrayVec3,
inspect: [ -0.1, -0.625, uiZ] as ArrayVec3,
deserializeDrawing: [ -0.3, -0.625, uiZ] as ArrayVec3,
openLink: [ 0.25, -0.275, uiZ] as ArrayVec3,
Expand Down
1 change: 1 addition & 0 deletions src/systems/bit-constraints-system.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const releaseBodyOptions = { activationState: ACTIVE_TAG };
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.updateRigidBodyOptions(eid, grabBodyOptions);
physicsSystem.addConstraint(interactor, Rigidbody.bodyId[eid], Rigidbody.bodyId[interactor], {});
addComponent(world, Constraint, eid);
Expand Down

0 comments on commit 8ac0b72

Please sign in to comment.