Skip to content

Commit

Permalink
Merge pull request #6434 from mozilla/pen-bitecs-interactables-compat
Browse files Browse the repository at this point in the history
Compat layer to fully support pen in bitECS
  • Loading branch information
keianhzo authored Jan 22, 2024
2 parents 4804f77 + 69ec7be commit c16e92f
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/bit-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ export const TextButton = defineComponent({ labelRef: Types.eid });
export const HoldableButton = defineComponent();
export const SingleActionButton = defineComponent();
export const Pen = defineComponent();
export const PenActive = defineComponent();
export const PenUpdated = defineComponent();
export const HoverMenuChild = defineComponent();
export const Static = defineComponent();
export const Inspectable = defineComponent();
Expand Down
17 changes: 12 additions & 5 deletions src/components/tools/pen.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
} from "../../systems/sound-effects-system";
import { waitForDOMContentLoaded } from "../../utils/async-utils";
import { convertStandardMaterial } from "../../utils/material-utils";
import { addComponent } from "bitecs";
import { PenUpdated } from "../../bit-components";
import { shouldUseNewLoader } from "../../utils/bit-utils";

const pathsMap = {
"player-right-controller": {
Expand Down Expand Up @@ -479,11 +482,15 @@ AFRAME.registerComponent("pen", {

populateEntities(targets) {
targets.length = 0;
// TODO: Do not querySelectorAll on the entire scene every time anything changes!
const els = AFRAME.scenes[0].querySelectorAll(".collidable, .interactable, #environment-root");
for (let i = 0; i < els.length; i++) {
if (!els[i].classList.contains("pen") && els[i].object3D) {
targets.push(els[i].object3D);
if (shouldUseNewLoader()) {
addComponent(APP.world, PenUpdated, this.el.eid);
} else {
// TODO: Do not querySelectorAll on the entire scene every time anything changes!
const els = AFRAME.scenes[0].querySelectorAll(".collidable, .interactable, #environment-root");
for (let i = 0; i < els.length; i++) {
if (!els[i].classList.contains("pen") && els[i].object3D) {
targets.push(els[i].object3D);
}
}
}
},
Expand Down
39 changes: 39 additions & 0 deletions src/systems/bit-pen-system.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { defineQuery, enterQuery, entityExists, hasComponent, removeComponent } from "bitecs";
import { HubsWorld } from "../app";
import { CursorRaycastable, Pen, PenActive, PenUpdated, SceneRoot } from "../bit-components";
import { PenComponent, PenToolsSystem } from "aframe";
import { Object3D } from "three";
import { EntityID } from "../utils/networking-types";
import { anyEntityWith } from "../utils/bit-utils";

function addTarget(world: HubsWorld, target: EntityID, targets: Object3D[]) {
const object = APP.world.eid2obj.get(target)!;
if (!hasComponent(world, Pen, target) && !targets.includes(object)) {
targets.push(object);
}
}

const raycastableQuery = defineQuery([CursorRaycastable]);
const sceneQuery = defineQuery([SceneRoot]);
const raycastableEnterQuery = enterQuery(raycastableQuery);
const penUpdateQuery = defineQuery([PenUpdated]);
const penUpdateEnterQuery = enterQuery(penUpdateQuery);
export function bitPenCompatSystem(world: HubsWorld, penToolsSystem: PenToolsSystem) {
const pen = penToolsSystem.myPen?.components["pen"] as PenComponent;
if (pen) {
removeComponent(world, PenUpdated, pen.el.eid);
}
if (anyEntityWith(world, PenActive)) {
penUpdateEnterQuery(world).forEach(eid => {
raycastableQuery(APP.world).forEach(eid => {
addTarget(world, eid, pen.targets);
});
sceneQuery(world).forEach(eid => {
addTarget(world, eid, pen.targets);
});
});
raycastableEnterQuery(world).forEach(eid => {
addTarget(world, eid, pen.targets);
});
}
}
10 changes: 6 additions & 4 deletions src/systems/hold-system.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ import {
AEntity,
Networked,
MediaLoader,
Deletable
Deletable,
PenActive
} from "../bit-components";
import { canMove } from "../utils/permissions-utils";
import { canMove as canMoveEntity } from "../utils/bit-permissions-utils";
import { isPinned } from "../bit-systems/networking";
import { takeOwnership } from "../utils/take-ownership";
import { findAncestorWithComponents } from "../utils/bit-utils";
import { anyEntityWith, findAncestorWithComponents } from "../utils/bit-utils";

const GRAB_REMOTE_RIGHT = paths.actions.cursor.right.grab;
const DROP_REMOTE_RIGHT = paths.actions.cursor.right.drop;
Expand Down Expand Up @@ -87,7 +88,8 @@ function grab(world, userinput, queryHovered, held, grabPath) {
target &&
userinput.get(grabPath) &&
(!isEntityPinned || AFRAME.scenes[0].is("frozen")) &&
hasPermissionToGrab(world, target)
hasPermissionToGrab(world, target) &&
!anyEntityWith(world, PenActive)
) {
if (hasComponent(world, Networked, target)) {
takeOwnership(world, target);
Expand All @@ -99,7 +101,7 @@ function grab(world, userinput, queryHovered, held, grabPath) {

function drop(world, userinput, queryHeld, held, dropPath) {
const heldEid = queryHeld(world)[0];
if (heldEid && userinput.get(dropPath)) {
if (heldEid && userinput.get(dropPath) && !anyEntityWith(world, PenActive)) {
// TODO: Drop on ownership lost
removeComponent(world, held, heldEid);

Expand Down
3 changes: 3 additions & 0 deletions src/systems/hubs-systems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import { mixerAnimatableSystem } from "../bit-systems/mixer-animatable";
import { loopAnimationSystem } from "../bit-systems/loop-animation";
import { linkSystem } from "../bit-systems/link-system";
import { objectMenuTransformSystem } from "../bit-systems/object-menu-transform-system";
import { bitPenCompatSystem } from "./bit-pen-system";

declare global {
interface Window {
Expand Down Expand Up @@ -277,6 +278,8 @@ export function mainTick(xrFrame: XRFrame, renderer: WebGLRenderer, scene: Scene
videoTextureSystem(world);
audioDebugSystem(world);

bitPenCompatSystem(world, aframeSystems["pen-tools"]);

deleteEntitySystem(world, aframeSystems.userinput);
destroyAtExtremeDistanceSystem(world);
removeNetworkedObjectButtonSystem(world);
Expand Down
8 changes: 8 additions & 0 deletions src/systems/pen-tools.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { addComponent, removeComponent } from "bitecs";
import { waitForDOMContentLoaded } from "../utils/async-utils";
import { Pen, PenActive } from "../bit-components";
import { anyEntityWith } from "../utils/bit-utils";

// Used for tracking and managing pen tools in the scene
AFRAME.registerSystem("pen-tools", {
Expand Down Expand Up @@ -32,7 +35,12 @@ AFRAME.registerSystem("pen-tools", {

if (this.myPen) {
this.sceneEl.addState("pen");
addComponent(APP.world, PenActive, this.myPen.eid);
} else {
const pen = anyEntityWith(APP.world, Pen);
if (pen) {
removeComponent(APP.world, PenActive, pen);
}
this.sceneEl.removeState("pen");
}
}
Expand Down
9 changes: 9 additions & 0 deletions types/aframe.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ declare module "aframe" {
invaders: PersonalSpaceInvader[];
}

interface PenToolsSystem extends ASystem {
myPen: AElement;
}

interface PenComponent extends AComponent {
targets: Object3D[];
}

interface TransformSelectedObjectSystem extends ASystem {
startTransform(targetObj: Object3D, handObj: Object3D, data: object): void;
stopTransform(): void;
Expand All @@ -119,6 +127,7 @@ declare module "aframe" {
/** @deprecated see bit-interaction-system */
interaction: InteractionSystem;
nav: NavSystem;
"pen-tools": PenToolsSystem;
};
emit(string, any?): void;
addState(string): void;
Expand Down

0 comments on commit c16e92f

Please sign in to comment.