Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bitECS: Fix grabbable pinned media objects #6231

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/bit-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export const MediaLoader = defineComponent({
MediaLoader.src[$isStringType] = true;
MediaLoader.fileId[$isStringType] = true;
export const MediaLoaded = defineComponent();
export const LoadedByMediaLoader = defineComponent();
export const MediaContentBounds = defineComponent({
bounds: [Types.f32, 3]
});
Expand Down
2 changes: 2 additions & 0 deletions src/bit-systems/media-loading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box3, Euler, Vector3 } from "three";
import { HubsWorld } from "../app";
import {
GLTFModel,
LoadedByMediaLoader,
MediaContentBounds,
MediaLoaded,
MediaLoader,
Expand Down Expand Up @@ -210,6 +211,7 @@ function* loadMedia(world: HubsWorld, eid: EntityID) {
console.error(e);
media = renderAsEntity(world, ErrorObject());
}
addComponent(world, LoadedByMediaLoader, media);
crClearTimeout(addLoadingObjectTimeout);
loadingObjEid && removeEntity(world, loadingObjEid);
return media;
Expand Down
56 changes: 55 additions & 1 deletion src/systems/hold-system.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
HeldHandRight,
HoveredHandLeft,
HeldHandLeft,
LoadedByMediaLoader,
AEntity
} from "../bit-components";
import { canMove } from "../utils/permissions-utils";
Expand Down Expand Up @@ -38,9 +39,62 @@ function isAEntityPinned(world, eid) {
return false;
}

// Special check for Droped/Pasted Media with new loader enabled.
//
// ** Problem **
// When you drop or paste a media file or url, a MediaLoader entity is created.
// This entity downloads the media file and creates a media (e.g., video)
// entity. The MediaLoader entity object then adds the media entity object
// as its child.
//
// The MediaLoader entity does not have a visible object after the loading
// cube disappears, but the media entity does. Both entities are hover targets,
// but after the loading cube disappears, the MediaLoader entity can no longer
// be hovered because it does not have a visible object. Only the media entity
// can be hovered at this point.
//
// The media entity is not a networked entity, but the MediaLoader entity is.
// This means that the MediaLoader entity can be pinned (the creator is "reticulum"),
// but the media entity cannot. If you check whether the media entity is pinned,
// it will always return false. Then media entity will always be grabbable even if
// it is pinned (more precisely its parent is pinned).
//
// **Solution**
// Check its parent is pinned to check media entity is pinned.
//
// TODO: This solution is hacky. Fix the root issue.
//
// 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.
function isParentPinned(world, eid) {
if (!world.eid2obj.has(eid)) {
return false;
}

const obj = world.eid2obj.get(eid);

if (obj.parent === null) {
return false;
}

const parent = obj.parent;

if (parent.eid === undefined) {
return false;
}

return isPinned(parent.eid);
}

function grab(world, userinput, queryHovered, held, grabPath) {
const hovered = queryHovered(world)[0];
const isEntityPinned = isPinned(hovered) || isAEntityPinned(world, hovered);
let isEntityPinned = isPinned(hovered) || isAEntityPinned(world, hovered);

// Special path for Dropped/Pasted Media with new loader enabled
if (!isEntityPinned && hasComponent(world, LoadedByMediaLoader, hovered)) {
isEntityPinned = isParentPinned(world, hovered);
}

if (
hovered &&
Expand Down