Skip to content

Commit

Permalink
Merge pull request #6450 from mozilla/bitecs-inspect-bug-fix
Browse files Browse the repository at this point in the history
Handle inspected entity removal cases gracefully
  • Loading branch information
keianhzo authored Jan 24, 2024
2 parents bf4927c + bb60afa commit add9afa
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 31 deletions.
5 changes: 3 additions & 2 deletions src/bit-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ export const PenActive = defineComponent();
export const PenUpdated = defineComponent();
export const HoverMenuChild = defineComponent();
export const Static = defineComponent();
export const Inspectable = defineComponent();
export const InspectTargetChanged = defineComponent();
export const Inspectable = defineComponent({
flags: Types.ui8
});
export const Inspected = defineComponent();
export const PreventAudioBoost = defineComponent();
export const IgnoreSpaceBubble = defineComponent();
Expand Down
17 changes: 11 additions & 6 deletions src/bit-systems/inspect-system.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import { defineQuery, enterQuery, exitQuery, hasComponent, removeComponent } from "bitecs";
import { defineQuery, enterQuery, exitQuery } from "bitecs";
import { HubsWorld } from "../app";
import { InspectTargetChanged, Inspected } from "../bit-components";
import { Inspectable, Inspected } from "../bit-components";
import { CameraSystem } from "../systems/camera-system";
import { anyEntityWith } from "../utils/bit-utils";

export const INSPECTABLE_FLAGS = {
TARGET_CHANGED: 1 << 0
};

const inspectedQuery = defineQuery([Inspected]);
const inspectedEnterQuery = enterQuery(inspectedQuery);
const inspectedExitQuery = exitQuery(inspectedQuery);
export function inspectSystem(world: HubsWorld, cameraSystem: CameraSystem) {
inspectedExitQuery(world).forEach(eid => {
cameraSystem.uninspect(hasComponent(world, InspectTargetChanged, eid));
removeComponent(world, InspectTargetChanged, eid);
const targetChanged = Boolean(Inspectable.flags[eid] & INSPECTABLE_FLAGS.TARGET_CHANGED);
cameraSystem.uninspect(targetChanged);
Inspectable.flags[eid] = 0;
});
inspectedEnterQuery(world).forEach(eid => {
const obj = world.eid2obj.get(eid);
cameraSystem.inspect(obj, 1.5, hasComponent(world, InspectTargetChanged, eid));
const targetChanged = Boolean(Inspectable.flags[eid] & INSPECTABLE_FLAGS.TARGET_CHANGED);
cameraSystem.inspect(obj, 1.5, targetChanged);
});
}
7 changes: 3 additions & 4 deletions src/bit-systems/object-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import {
MediaMirrored,
Inspected,
Inspectable,
Deletable,
InspectTargetChanged
Deletable
} from "../bit-components";
import {
anyEntityWith,
Expand All @@ -45,6 +44,7 @@ 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";
import { INSPECTABLE_FLAGS } from "./inspect-system";
// Working variables.
const _vec3_1 = new Vector3();
const _vec3_2 = new Vector3();
Expand Down Expand Up @@ -226,7 +226,7 @@ function handleHeldEnter(world: HubsWorld, eid: EntityID, menuEid: EntityID) {
if (!hasComponent(world, Inspected, ObjectMenu.targetRef[menuEid])) {
ObjectMenu.flags[menuEid] &= ~ObjectMenuFlags.Visible;
addComponent(world, Inspected, ObjectMenu.targetRef[menuEid]);
addComponent(world, InspectTargetChanged, ObjectMenu.targetRef[menuEid]);
Inspectable.flags[ObjectMenu.targetRef[menuEid]] |= INSPECTABLE_FLAGS.TARGET_CHANGED;
}
break;
}
Expand All @@ -246,7 +246,6 @@ function handleHeldExit(world: HubsWorld, eid: EntityID, menuEid: EntityID) {
if (hasComponent(world, Inspected, ObjectMenu.targetRef[menuEid])) {
ObjectMenu.flags[menuEid] |= ObjectMenuFlags.Visible;
removeComponent(world, Inspected, ObjectMenu.targetRef[menuEid]);
addComponent(world, InspectTargetChanged, ObjectMenu.targetRef[menuEid]);
}
break;
}
Expand Down
31 changes: 21 additions & 10 deletions src/react-components/room/hooks/useObjectList.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ export function ObjectListProvider({ scene, children }) {
eid: eid
}));
setObjects(objects);

const inspected = anyEntityWith(APP.world, Inspected);
if (!inspected || !objects.find(o => o.eid === inspected)) {
setSelectedObject(null);
}
} else {
const objects = scene.systems["listed-media"].els.sort(mediaSortAframe).map(el => ({
id: el.object3D.id,
Expand All @@ -126,6 +131,13 @@ export function ObjectListProvider({ scene, children }) {
el
}));
setObjects(objects);

const cameraSystem = scene.systems["hubs-systems"].cameraSystem;
const inspectedEl = cameraSystem.inspectable && cameraSystem.inspectable.el;

if (!inspectedEl || !objects.find(o => o.el === inspectedEl)) {
setSelectedObject(null);
}
}
}

Expand All @@ -145,32 +157,31 @@ export function ObjectListProvider({ scene, children }) {
scene.removeEventListener("listed_media_changed", updateMediaEntities);
clearTimeout(timeout);
};
}, [scene, setObjects]);
}, [scene, setObjects, setSelectedObject]);

useEffect(() => {
function onInspectTargetChanged() {
const cameraSystem = scene.systems["hubs-systems"].cameraSystem;

if (shouldUseNewLoader()) {
const inspectedEid = cameraSystem.inspectable && cameraSystem.inspectable.eid;
const inspected = anyEntityWith(APP.world, Inspected);

if (inspectedEid) {
const object = objects.find(o => o.eid === inspectedEid);
if (inspected) {
const object = objects.find(o => o.eid === inspected);

if (object) {
setSelectedObject(object);
} else {
setSelectedObject({
id: APP.world.eid2obj.get(inspectedEid)?.id,
name: getDisplayString(getUrl(inspectedEid)),
type: getMediaType(inspectedEid),
eid: inspectedEid
id: APP.world.eid2obj.get(inspected)?.id,
name: getDisplayString(getUrl(inspected)),
type: getMediaType(inspected),
eid: inspected
});
}
} else {
setSelectedObject(null);
}
} else {
const cameraSystem = scene.systems["hubs-systems"].cameraSystem;
const inspectedEl = cameraSystem.inspectable && cameraSystem.inspectable.el;

if (inspectedEl) {
Expand Down
12 changes: 3 additions & 9 deletions src/systems/camera-system.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,15 @@ import { qsGet } from "../utils/qs_truthy";
const customFOV = qsGet("fov");
const enableThirdPersonMode = qsTruthy("thirdPerson");
import { Layers } from "../camera-layers";
import {
HoveredRemoteRight,
InspectTargetChanged,
Inspectable,
Inspected,
LocalAvatar,
RemoteAvatar
} from "../bit-components";
import { HoveredRemoteRight, Inspectable, Inspected, LocalAvatar, RemoteAvatar } from "../bit-components";
import {
anyEntityWith,
findAncestorWithAnyComponent,
findAncestorWithComponent,
shouldUseNewLoader
} from "../utils/bit-utils";
import { addComponent, defineQuery, removeComponent } from "bitecs";
import { INSPECTABLE_FLAGS } from "../bit-systems/inspect-system";

function getInspectableInHierarchy(eid) {
let inspectable = findAncestorWithComponent(APP.world, Inspectable, eid);
Expand Down Expand Up @@ -473,7 +467,7 @@ export class CameraSystem {
if (hoveredQuery(APP.world).length) {
const hovered = hoveredQuery(APP.world)[0];
addComponent(APP.world, Inspected, hovered);
addComponent(APP.world, InspectTargetChanged, hovered);
Inspectable.flags[hovered] |= INSPECTABLE_FLAGS.TARGET_CHANGED;
}
} else {
const hoverEl = this.interaction.state.rightRemote.hovered || this.interaction.state.leftRemote.hovered;
Expand Down

0 comments on commit add9afa

Please sign in to comment.