Skip to content

Commit

Permalink
Support media with link component
Browse files Browse the repository at this point in the history
  • Loading branch information
keianhzo committed Sep 19, 2023
1 parent 8653fdd commit 322dc3e
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 12 deletions.
3 changes: 2 additions & 1 deletion src/bit-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ export const MyCameraTool = defineComponent();
export const MediaLoader = defineComponent({
src: Types.ui32,
flags: Types.ui8,
fileId: Types.ui32
fileId: Types.ui32,
linkSrc: Types.ui32
});
MediaLoader.src[$isStringType] = true;
MediaLoader.fileId[$isStringType] = true;
Expand Down
29 changes: 23 additions & 6 deletions src/bit-systems/media-loading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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 @@ -178,36 +180,51 @@ 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);
}

const linkSrc = APP.getString(MediaLoader.linkSrc[eid]);
if (linkSrc) {
inflateLink(world, mediaEid, { href: linkSrc, type: LinkType.LINK });
inflateGrabbable(world, mediaEid, { cursor: true, hand: false });
}

return mediaEid;
}

function* loadMedia(world: HubsWorld, eid: EntityID) {
Expand Down
15 changes: 14 additions & 1 deletion src/components/gltf-model-plus.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,13 +577,26 @@ 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)) {
props["linkSrc"] = 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
5 changes: 4 additions & 1 deletion src/inflators/image-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export interface ImageLoaderParams {
projection: ProjectionModeName;
alphaMode: AlphaModeName;
alphaCutoff: number;
linkSrc?: string;
controls: true;
}

const DEFAULTS: Partial<ImageLoaderParams> = {
Expand All @@ -23,7 +25,8 @@ export function inflateImageLoader(world: HubsWorld, eid: number, params: ImageL
recenter: false,
resize: false,
animateLoad: false,
isObjectMenuTarget: false
isObjectMenuTarget: params.linkSrc && params.controls ? true : false,
linkSrc: params.controls ? params.linkSrc : undefined
});

const requiredParams = Object.assign({}, DEFAULTS, params) as Required<ImageLoaderParams>;
Expand Down
6 changes: 5 additions & 1 deletion src/inflators/media-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ export type MediaLoaderParams = {
animateLoad: boolean;
fileId?: string;
isObjectMenuTarget: boolean;
linkSrc?: string;
};

export function inflateMediaLoader(
world: HubsWorld,
eid: number,
{ src, recenter, resize, animateLoad, fileId, isObjectMenuTarget }: MediaLoaderParams
{ src, recenter, resize, animateLoad, fileId, isObjectMenuTarget, linkSrc }: MediaLoaderParams
) {
addComponent(world, MediaLoader, eid);
let flags = 0;
Expand All @@ -28,4 +29,7 @@ export function inflateMediaLoader(
MediaLoader.fileId[eid] = APP.getSid(fileId)!;
}
MediaLoader.src[eid] = APP.getSid(src)!;
if (linkSrc) {
MediaLoader.linkSrc[eid] = APP.getSid(linkSrc)!;
}
}
4 changes: 3 additions & 1 deletion src/inflators/model-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { inflateMediaLoader } from "./media-loader";

export type ModelLoaderParams = {
src: string;
linkSrc?: string;
};

export function inflateModelLoader(world: HubsWorld, eid: number, params: ModelLoaderParams) {
Expand All @@ -11,6 +12,7 @@ export function inflateModelLoader(world: HubsWorld, eid: number, params: ModelL
recenter: true,
resize: false,
animateLoad: false,
isObjectMenuTarget: false
isObjectMenuTarget: params.linkSrc ? true : false,
linkSrc: params.linkSrc
});
}
4 changes: 3 additions & 1 deletion src/inflators/video-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface VideoLoaderParams {
autoPlay: boolean;
controls: boolean;
loop: boolean;
linkSrc?: string;
}

const DEFAULTS: Partial<VideoLoaderParams> = {
Expand All @@ -24,7 +25,8 @@ export function inflateVideoLoader(world: HubsWorld, eid: number, params: VideoL
recenter: false,
resize: false,
animateLoad: false,
isObjectMenuTarget: false
isObjectMenuTarget: params.linkSrc && params.controls ? true : false,
linkSrc: params.controls ? params.linkSrc : undefined
});

const requiredParams = Object.assign({}, DEFAULTS, params) as Required<VideoLoaderParams>;
Expand Down

0 comments on commit 322dc3e

Please sign in to comment.