Skip to content

Commit

Permalink
Merge pull request #6272 from mozilla/bitecs-media-with-link
Browse files Browse the repository at this point in the history
bitECS: Support media with link component
  • Loading branch information
keianhzo authored Oct 12, 2023
2 parents 484a3fb + 91ec811 commit d9c7904
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/bit-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,7 @@ export const TrimeshTag = defineComponent();
export const HeightFieldTag = defineComponent();
export const LocalAvatar = defineComponent();
export const RemoteAvatar = defineComponent();
export const MediaLink = defineComponent({
src: Types.ui32
});
MediaLink.src[$isStringType] = true;
29 changes: 23 additions & 6 deletions src/bit-systems/media-loading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
MediaContentBounds,
MediaImageLoaderData,
MediaInfo,
MediaLink,
MediaLoaded,
MediaLoader,
MediaVideoLoaderData,
Expand All @@ -31,6 +32,8 @@ import { loadAudio } from "../utils/load-audio";
import { loadHtml } from "../utils/load-html";
import { MediaType, mediaTypeName, resolveMediaInfo } from "../utils/media-utils";
import { EntityID } from "../utils/networking-types";
import { LinkType, inflateLink } from "../inflators/link";
import { inflateGrabbable } from "../inflators/grabbable";

const getBox = (() => {
const rotation = new Euler();
Expand Down Expand Up @@ -179,36 +182,50 @@ function* loadByMediaType(
// content then using MediaImage/VideoLoaderData as like
// transporting data from the inflators. This may be like
// special and a bit less maintainable.
let mediaEid;
switch (mediaType) {
case MediaType.IMAGE:
return yield* loadImage(
mediaEid = yield* loadImage(
world,
accessibleUrl,
contentType,
MediaImageLoaderData.has(eid) ? MediaImageLoaderData.get(eid)! : {}
);
break;
case MediaType.VIDEO:
return yield* loadVideo(
mediaEid = yield* loadVideo(
world,
accessibleUrl,
contentType,
MediaVideoLoaderData.has(eid) ? MediaVideoLoaderData.get(eid)! : {}
);
break;
case MediaType.MODEL:
return yield* loadModel(world, accessibleUrl, contentType, true);
mediaEid = yield* loadModel(world, accessibleUrl, contentType, true);
break;
case MediaType.PDF:
return yield* loadPDF(world, accessibleUrl);
mediaEid = yield* loadPDF(world, accessibleUrl);
break;
case MediaType.AUDIO:
return yield* loadAudio(
mediaEid = yield* loadAudio(
world,
accessibleUrl,
MediaVideoLoaderData.has(eid) ? MediaVideoLoaderData.get(eid)! : {}
);
break;
case MediaType.HTML:
return yield* loadHtml(world, canonicalUrl, thumbnail);
mediaEid = yield* loadHtml(world, canonicalUrl, thumbnail);
break;
default:
throw new UnsupportedMediaTypeError(eid, mediaType);
}

if (hasComponent(world, MediaLink, eid)) {
inflateLink(world, mediaEid, { href: APP.getString(MediaLink.src[eid])!, type: LinkType.LINK });
inflateGrabbable(world, mediaEid, { cursor: true, hand: false });
}

return mediaEid;
}

function* loadMedia(world: HubsWorld, eid: EntityID) {
Expand Down
17 changes: 16 additions & 1 deletion src/components/gltf-model-plus.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,13 +577,28 @@ class GLTFHubsComponentsExtension {
};
}

// It seems to be a pretty common use case to add a link to a media to show a link when hovering.
// That was supported in the previous loader but in the new loader it loads as two different entities.
// This hack adds support for linked media using the new loader.
// Note: For some reason this was not supported for PDFs. Not sure if it's random or if there is a reason.
if (shouldUseNewLoader()) {
if (Object.prototype.hasOwnProperty.call(ext, "link")) {
if (["image", "video", "model"].includes(componentName)) {
ext["media-link"] = {
src: ext.link.href
};
delete ext.link;
}
}
}

const value = props[propName];
const type = value?.__mhc_link_type;
if (type && value.index !== undefined) {
deps.push(
parser.getDependency(type, value.index).then(loadedDep => {
// TODO similar to above, this logic being spread out in multiple places is not great...
// Node refences are assumed to always be in the scene graph. These referneces are late-resolved in inflateComponents
// Node references are assumed to always be in the scene graph. These references are late-resolved in inflateComponents
// otherwise they will need to be updated when cloning (which happens as part of caching).
if (type === "node") return;

Expand Down
13 changes: 13 additions & 0 deletions src/inflators/media-link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { addComponent } from "bitecs";
import { HubsWorld } from "../app";
import { EntityID } from "../utils/networking-types";
import { MediaLink } from "../bit-components";

export type MediaLinkParams = {
src: string;
};

export function inflateMediaLink(world: HubsWorld, eid: EntityID, params: MediaLinkParams) {
addComponent(world, MediaLink, eid);
MediaLink.src[eid] = APP.getSid(params.src);
}
7 changes: 5 additions & 2 deletions src/utils/jsx-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ import { inflateTrimesh } from "../inflators/trimesh";
import { HeightFieldParams, inflateHeightField } from "../inflators/heightfield";
import { inflateAudioSettings } from "../inflators/audio-settings";
import { HubsVideoTexture } from "../textures/HubsVideoTexture";
import { inflateMediaLink, MediaLinkParams } from "../inflators/media-link";

preload(
new Promise(resolve => {
Expand Down Expand Up @@ -380,6 +381,7 @@ export interface GLTFComponentData extends ComponentData {
zoneAudioSource: AudioSourceParams;
audioTarget: AudioTargetParams;
audioSettings: SceneAudioSettings;
mediaLink: MediaLinkParams;

// deprecated
spawnPoint?: true;
Expand Down Expand Up @@ -472,7 +474,7 @@ const jsxInflators: Required<{ [K in keyof JSXComponentData]: InflatorFn }> = {
model: inflateModel,
image: inflateImage,
video: inflateVideo,
link: inflateLink,
link: inflateLink
};

export const gltfInflators: Required<{ [K in keyof GLTFComponentData]: InflatorFn }> = {
Expand Down Expand Up @@ -507,7 +509,8 @@ export const gltfInflators: Required<{ [K in keyof GLTFComponentData]: InflatorF
boxCollider: inflateBoxCollider,
trimesh: inflateTrimesh,
heightfield: inflateHeightField,
audioSettings: inflateAudioSettings
audioSettings: inflateAudioSettings,
mediaLink: inflateMediaLink
};

function jsxInflatorExists(name: string): name is keyof JSXComponentData {
Expand Down

0 comments on commit d9c7904

Please sign in to comment.