From ed7f19ca7ca334a3e88533db0821c4f1db84c6f1 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Wed, 10 May 2023 16:29:07 +0200 Subject: [PATCH] bitECS object list support This commit adds bitECS object list support. **Basic Strategy** Reuse the existing A-Frame based code as much as possible for now. In the related functions that take A-Frame element, take Object3D instead. Object3D has a reference to A-Frame element in the A-Frame based implementation and has a reference to Entity ID in the bitECS. The functions process with A-Frame element or Entity ID depending on whether new loader enabled. Explicitly use shouldUseNewLoader() and/or make two functions, one for A-Frame based and another one for bitECS based implementation, if different logics are needed between A-Frame based and bitECS based implementations. Duplicated codes may not be perfectly removed but it would be simpler to follow the code rather than the new loader pretends the old one. And it would be easier to edit the code when we will get rid of A-Frame. **Changes** - Introduce MediaInfo component and save url and content type into it when loading media in media-loader. The info is used in the object list - Fire listed_media_changed event when media is loaded via media-loader and when the loaded media entity is removed - Take Object3D instead of A-Frame element in the related functions - Use shouldUseNewLoader() and/or make two separated functions for A-Frame and bitECS where the different logics are needed **Future TODOs** - Support avatars - Support Pinning --- src/bit-components.js | 6 + src/bit-systems/media-loading.ts | 10 ++ src/components/media-loader.js | 4 +- src/components/super-spawner.js | 2 +- src/prefabs/media.tsx | 1 + .../room/hooks/useObjectList.js | 104 +++++++++++++----- src/react-components/room/object-hooks.js | 50 +++++++-- src/systems/camera-system.js | 56 +++++++--- src/utils/auto-box-collider.js | 16 +-- src/utils/jsx-entity.ts | 6 +- src/utils/media-sorting.js | 51 +++++---- 11 files changed, 217 insertions(+), 89 deletions(-) diff --git a/src/bit-components.js b/src/bit-components.js index 0059457998b..c94f0533ab7 100644 --- a/src/bit-components.js +++ b/src/bit-components.js @@ -161,6 +161,12 @@ export const LoadedByMediaLoader = defineComponent(); export const MediaContentBounds = defineComponent({ bounds: [Types.f32, 3] }); +export const MediaInfo = defineComponent({ + accessibleUrl: Types.ui32, + contentType: Types.ui32 +}); +MediaInfo.accessibleUrl[$isStringType] = true; +MediaInfo.contentType[$isStringType] = true; export const SceneRoot = defineComponent(); export const NavMesh = defineComponent(); diff --git a/src/bit-systems/media-loading.ts b/src/bit-systems/media-loading.ts index cdb1ef64c4b..2826ce7b3b0 100644 --- a/src/bit-systems/media-loading.ts +++ b/src/bit-systems/media-loading.ts @@ -5,6 +5,7 @@ import { GLTFModel, LoadedByMediaLoader, MediaContentBounds, + MediaInfo, MediaLoaded, MediaLoader, Networked, @@ -207,6 +208,9 @@ function* loadMedia(world: HubsWorld, eid: EntityID) { } media = yield* loader(world, eid, urlData); addComponent(world, MediaLoaded, media); + addComponent(world, MediaInfo, media); + MediaInfo.accessibleUrl[media] = APP.getSid(urlData.accessibleUrl); + MediaInfo.contentType[media] = APP.getSid(urlData.contentType); } catch (e) { console.error(e); media = renderAsEntity(world, ErrorObject()); @@ -252,6 +256,9 @@ const jobs = new JobRunner(); const mediaLoaderQuery = defineQuery([MediaLoader]); const mediaLoaderEnterQuery = enterQuery(mediaLoaderQuery); const mediaLoaderExitQuery = exitQuery(mediaLoaderQuery); +const mediaLoadedQuery = defineQuery([MediaLoaded]); +const mediaLoadedEnterQuery = enterQuery(mediaLoadedQuery); +const mediaLoadedExitQuery = exitQuery(mediaLoadedQuery); export function mediaLoadingSystem(world: HubsWorld) { mediaLoaderEnterQuery(world).forEach(function (eid) { jobs.add(eid, clearRollbacks => loadAndAnimateMedia(world, eid, clearRollbacks)); @@ -261,5 +268,8 @@ export function mediaLoadingSystem(world: HubsWorld) { jobs.stop(eid); }); + mediaLoadedEnterQuery(world).forEach(() => APP.scene?.emit("listed_media_changed")); + mediaLoadedExitQuery(world).forEach(() => APP.scene?.emit("listed_media_changed")); + jobs.tick(); } diff --git a/src/components/media-loader.js b/src/components/media-loader.js index 0c631213852..e76eb883549 100644 --- a/src/components/media-loader.js +++ b/src/components/media-loader.js @@ -111,7 +111,7 @@ AFRAME.registerComponent("media-loader", { setMatrixWorld(mesh, originalMeshMatrix); } else { // Move the mesh such that the center of its bounding box is in the same position as the parent matrix position - const box = getBox(this.el, mesh); + const box = getBox(this.el.object3D, mesh); const scaleCoefficient = fitToBox ? getScaleCoefficient(0.5, box) : 1; const { min, max } = box; center.addVectors(min, max).multiplyScalar(0.5 * scaleCoefficient); @@ -283,7 +283,7 @@ AFRAME.registerComponent("media-loader", { } // TODO this does duplicate work in some cases, but finish() is the only consistent place to do it - const contentBounds = getBox(this.el, this.el.getObject3D("mesh")).getSize(new THREE.Vector3()); + const contentBounds = getBox(this.el.object3D, this.el.getObject3D("mesh")).getSize(new THREE.Vector3()); addComponent(APP.world, MediaContentBounds, el.eid); MediaContentBounds.bounds[el.eid].set(contentBounds.toArray()); diff --git a/src/components/super-spawner.js b/src/components/super-spawner.js index 2c17fb5cef6..7843bc0e808 100644 --- a/src/components/super-spawner.js +++ b/src/components/super-spawner.js @@ -111,7 +111,7 @@ AFRAME.registerComponent("super-spawner", { ? 1 : 0.5; - const scaleCoefficient = getScaleCoefficient(boxSize, getBox(spawnedEntity, spawnedEntity.object3D)); + const scaleCoefficient = getScaleCoefficient(boxSize, getBox(spawnedEntity.object3D, spawnedEntity.object3D)); this.spawnedMediaScale.divideScalar(scaleCoefficient); }, diff --git a/src/prefabs/media.tsx b/src/prefabs/media.tsx index 6718c5a2390..cacb88ef5c4 100644 --- a/src/prefabs/media.tsx +++ b/src/prefabs/media.tsx @@ -28,6 +28,7 @@ export function MediaPrefab(params: MediaLoaderParams): EntityDef { collisionMask: COLLISION_LAYERS.HANDS }} scale={[1, 1, 1]} + inspectable /> ); } diff --git a/src/react-components/room/hooks/useObjectList.js b/src/react-components/room/hooks/useObjectList.js index 26367bdb859..79e9f7c77fb 100644 --- a/src/react-components/room/hooks/useObjectList.js +++ b/src/react-components/room/hooks/useObjectList.js @@ -1,11 +1,21 @@ import React, { useState, useEffect, useContext, createContext, useCallback, Children, cloneElement } from "react"; import PropTypes from "prop-types"; -import { mediaSort, getMediaType } from "../../../utils/media-sorting.js"; +import { mediaSort, mediaSortAframe, getMediaType, getMediaTypeAframe } from "../../../utils/media-sorting.js"; +import { shouldUseNewLoader } from "../../../utils/bit-utils"; +import { defineQuery, hasComponent } from "bitecs"; +import { MediaInfo } from "../../../bit-components.js"; -function getDisplayString(el) { +function getUrl(eid) { + return hasComponent(APP.world, MediaInfo, eid) ? APP.getString(MediaInfo.accessibleUrl[eid]) : ""; +} + +function getUrlAframe(el) { // Having a listed-media component does not guarantee the existence of a media-loader component, // so don't crash if there isn't one. - const url = (el.components["media-loader"] && el.components["media-loader"].data.src) || ""; + return (el.components["media-loader"] && el.components["media-loader"].data.src) || ""; +} + +function getDisplayString(url) { const split = url.split("/"); const resourceName = split[split.length - 1].split("?")[0]; let httpIndex = -1; @@ -46,12 +56,14 @@ function handleInspect(scene, object, callback) { callback(object); - if (object.el.object3D !== cameraSystem.inspectable) { + const object3D = shouldUseNewLoader() ? APP.world.eid2obj.get(object.eid) : object.el.object3D; + + if (object3D !== cameraSystem.inspectable) { if (cameraSystem.inspectable) { cameraSystem.uninspect(false); } - cameraSystem.inspect(object.el, 1.5, false); + cameraSystem.inspect(object3D, 1.5, false); } } @@ -63,10 +75,12 @@ function handleDeselect(scene, object, callback) { cameraSystem.uninspect(false); if (object) { - cameraSystem.inspect(object.el, 1.5, false); + const object3D = shouldUseNewLoader() ? APP.world.eid2obj.get(object.eid) : object.el.object3D; + cameraSystem.inspect(object3D, 1.5, false); } } +const queryListedMedia = defineQuery([MediaInfo]); export function ObjectListProvider({ scene, children }) { const [objects, setObjects] = useState([]); const [focusedObject, setFocusedObject] = useState(null); // The object currently shown in the viewport @@ -76,14 +90,26 @@ export function ObjectListProvider({ scene, children }) { useEffect(() => { function updateMediaEntities() { - const objects = scene.systems["listed-media"].els.sort(mediaSort).map(el => ({ - id: el.object3D.id, - name: getDisplayString(el), - type: getMediaType(el), - el - })); - - setObjects(objects); + if (shouldUseNewLoader()) { + const objects = queryListedMedia(APP.world) + .sort(mediaSort) + .map(eid => ({ + id: APP.world.eid2obj.get(eid)?.id, + name: getDisplayString(getUrl(eid)), + type: getMediaType(eid), + eid: eid + })); + setObjects(objects); + } else { + const objects = scene.systems["listed-media"].els.sort(mediaSortAframe).map(el => ({ + id: el.object3D.id, + name: getDisplayString(getUrlAframe(el)), + type: getMediaTypeAframe(el), + eid: el.eid, + el + })); + setObjects(objects); + } } let timeout; @@ -108,23 +134,45 @@ export function ObjectListProvider({ scene, children }) { function onInspectTargetChanged() { const cameraSystem = scene.systems["hubs-systems"].cameraSystem; - const inspectedEl = cameraSystem.inspectable && cameraSystem.inspectable.el; - - if (inspectedEl) { - const object = objects.find(o => o.el === inspectedEl); - - if (object) { - setSelectedObject(object); + if (shouldUseNewLoader()) { + const inspectedEid = cameraSystem.inspectable && cameraSystem.inspectable.eid; + + if (inspectedEid) { + const object = objects.find(o => o.eid === inspectedEid); + + if (object) { + setSelectedObject(object); + } else { + setSelectedObject({ + id: APP.world.eid2obj.get(inspectedEid)?.id, + name: getDisplayString(getUrl(inspectedEid)), + type: getMediaType(inspectedEid), + eid: inspectedEid + }); + } } else { - setSelectedObject({ - id: inspectedEl.object3D.id, - name: getDisplayString(inspectedEl), - type: getMediaType(inspectedEl), - el: inspectedEl - }); + setSelectedObject(null); } } else { - setSelectedObject(null); + const inspectedEl = cameraSystem.inspectable && cameraSystem.inspectable.el; + + if (inspectedEl) { + const object = objects.find(o => o.el === inspectedEl); + + if (object) { + setSelectedObject(object); + } else { + setSelectedObject({ + id: inspectedEl.object3D.id, + name: getDisplayString(getUrlAframe(inspectedEl)), + type: getMediaTypeAframe(inspectedEl), + eid: inspectedEl.eid, + el: inspectedEl + }); + } + } else { + setSelectedObject(null); + } } } diff --git a/src/react-components/room/object-hooks.js b/src/react-components/room/object-hooks.js index 1cc4861c6ae..50553a5966c 100644 --- a/src/react-components/room/object-hooks.js +++ b/src/react-components/room/object-hooks.js @@ -1,24 +1,36 @@ import { useEffect, useState, useCallback, useMemo } from "react"; import { removeNetworkedObject } from "../../utils/removeNetworkedObject"; +import { shouldUseNewLoader } from "../../utils/bit-utils"; import { rotateInPlaceAroundWorldUp, affixToWorldUp } from "../../utils/three-utils"; import { getPromotionTokenForFile } from "../../utils/media-utils"; import { hasComponent } from "bitecs"; -import { Static } from "../../bit-components"; import { isPinned as getPinnedState } from "../../bit-systems/networking"; +import { MediaInfo, Static } from "../../bit-components"; +import { deleteTheDeletableAncestor } from "../../bit-systems/delete-entity-system"; export function isMe(object) { - return object.el.id === "avatar-rig"; + return object.id === "avatar-rig"; } export function isPlayer(object) { - return !!object.el.components["networked-avatar"]; + if (shouldUseNewLoader()) { + // TODO Add when networked avatar is migrated + return false; + } else { + return !!object.el.components["networked-avatar"]; + } } export function getObjectUrl(object) { - const mediaLoader = object.el.components["media-loader"]; - - const url = - mediaLoader && ((mediaLoader.data.mediaOptions && mediaLoader.data.mediaOptions.href) || mediaLoader.data.src); + let url; + if (shouldUseNewLoader()) { + const urlSid = MediaInfo.accessibleUrl[object.eid]; + url = APP.getString(urlSid); + } else { + const mediaLoader = object.el.components["media-loader"]; + url = + mediaLoader && ((mediaLoader.data.mediaOptions && mediaLoader.data.mediaOptions.href) || mediaLoader.data.src); + } if (url && !url.startsWith("hubs://")) { return url; @@ -28,7 +40,7 @@ export function getObjectUrl(object) { } export function usePinObject(hubChannel, scene, object) { - const [isPinned, setIsPinned] = useState(getPinnedState(object.el.eid)); + const [isPinned, setIsPinned] = useState(getPinnedState(object.eid)); const pinObject = useCallback(() => { const el = object.el; @@ -51,6 +63,11 @@ export function usePinObject(hubChannel, scene, object) { }, [isPinned, pinObject, unpinObject]); useEffect(() => { + // TODO Add when pinning is migrated + if (shouldUseNewLoader()) { + return; + } + const el = object.el; function onPinStateChanged() { @@ -65,6 +82,11 @@ export function usePinObject(hubChannel, scene, object) { }; }, [object]); + if (shouldUseNewLoader()) { + // TODO Add when pinning is migrated + return false; + } + const el = object.el; let userOwnsFile = false; @@ -114,16 +136,20 @@ export function useGoToSelectedObject(scene, object) { export function useRemoveObject(hubChannel, scene, object) { const removeObject = useCallback(() => { - removeNetworkedObject(scene, object.el); + if (shouldUseNewLoader()) { + deleteTheDeletableAncestor(APP.world, object.eid); + } else { + removeNetworkedObject(scene, object.el); + } }, [scene, object]); - const el = object.el; + const eid = object.eid; const canRemoveObject = !!( scene.is("entered") && !isPlayer(object) && - !getPinnedState(el.eid) && - !hasComponent(APP.world, Static, el.eid) && + !getPinnedState(eid) && + !hasComponent(APP.world, Static, eid) && hubChannel.can("spawn_and_move_media") ); diff --git a/src/systems/camera-system.js b/src/systems/camera-system.js index ee6cdbeee70..988e7132b3e 100644 --- a/src/systems/camera-system.js +++ b/src/systems/camera-system.js @@ -8,8 +8,19 @@ import { qsGet } from "../utils/qs_truthy"; const customFOV = qsGet("fov"); const enableThirdPersonMode = qsTruthy("thirdPerson"); import { Layers } from "../camera-layers"; +import { Inspectable } from "../bit-components"; +import { findAncestorWithComponent, shouldUseNewLoader } from "../utils/bit-utils"; + +function getInspectableInHierarchy(eid) { + let inspectable = findAncestorWithComponent(APP.world, Inspectable, eid); + if (!inspectable) { + console.warn("could not find inspectable in hierarchy"); + inspectable = eid; + } + return APP.world.eid2obj.get(inspectable); +} -function getInspectableInHierarchy(el) { +function getInspectableInHierarchyAframe(el) { let inspectable = el; while (inspectable) { if (isTagged(inspectable, "inspectable")) { @@ -36,8 +47,14 @@ function pivotFor(el) { return child.object3D; } -export function getInspectableAndPivot(el) { - const inspectable = getInspectableInHierarchy(el); +function getInspectableAndPivot(eid) { + const inspectable = getInspectableInHierarchy(eid); + // TODO Add support for pivotFor (avatars only) + return { inspectable, pivot: inspectable }; +} + +function getInspectableAndPivotAframe(el) { + const inspectable = getInspectableInHierarchyAframe(el); const pivot = pivotFor(inspectable.el); return { inspectable, pivot }; } @@ -119,22 +136,16 @@ const moveRigSoCameraLooksAtPivot = (function () { decompose(camera.matrixWorld, cwp, cwq); rig.getWorldQuaternion(cwq); - const box = getBox(inspectable.el, inspectable.el.getObject3D("mesh") || inspectable, true); + const box = getBox(inspectable, inspectable, true); if (box.min.x === Infinity) { // fix edgecase where inspectable object has no mesh / dimensions box.min.subVectors(owp, defaultBoxMax); box.max.addVectors(owp, defaultBoxMax); } box.getCenter(center); - const vrMode = inspectable.el.sceneEl.is("vr-mode"); + const vrMode = APP.scene.is("vr-mode"); const dist = - calculateViewingDistance( - inspectable.el.sceneEl.camera.fov, - inspectable.el.sceneEl.camera.aspect, - box, - center, - vrMode - ) * distanceMod; + calculateViewingDistance(APP.scene.camera.fov, APP.scene.camera.aspect, box, center, vrMode) * distanceMod; target.position.addVectors( owp, oForw @@ -252,15 +263,17 @@ export class CameraSystem { this.mode = NEXT_MODES[this.mode] || 0; } - inspect(el, distanceMod, fireChangeEvent = true) { - const { inspectable, pivot } = getInspectableAndPivot(el); - + inspect(obj, distanceMod, fireChangeEvent = true) { this.verticalDelta = 0; this.horizontalDelta = 0; this.inspectZoom = 0; + if (this.mode === CAMERA_MODE_INSPECT) { return; } + + const { inspectable, pivot } = shouldUseNewLoader() ? getInspectableAndPivot(obj.eid) : getInspectableAndPivotAframe(obj.el); + const scene = AFRAME.scenes[0]; scene.object3D.traverse(ensureLightsAreSeenByCamera); scene.classList.add("hand-cursor"); @@ -282,7 +295,16 @@ export class CameraSystem { this.viewingCamera.updateMatrices(); this.snapshot.matrixWorld.copy(this.viewingRig.object3D.matrixWorld); - this.snapshot.audio = !(inspectable.el && isTagged(inspectable.el, "preventAudioBoost")) && getAudio(inspectable); + let preventAudioBoost; + + if (shouldUseNewLoader()) { + // TODO Add when avatar is migrated + preventAudioBoost = false; + } else { + preventAudioBoost = inspectable.el && isTagged(inspectable.el, "preventAudioBoost"); + } + + this.snapshot.audio = !preventAudioBoost && getAudio(inspectable); if (this.snapshot.audio) { this.snapshot.audio.updateMatrices(); this.snapshot.audioTransform.copy(this.snapshot.audio.matrixWorld); @@ -427,7 +449,7 @@ export class CameraSystem { const hoverEl = this.interaction.state.rightRemote.hovered || this.interaction.state.leftRemote.hovered; if (hoverEl) { - this.inspect(hoverEl, 1.5); + this.inspect(hoverEl.object3D, 1.5); } } else if (this.mode === CAMERA_MODE_INSPECT && this.userinput.get(paths.actions.stopInspecting)) { scene.emit("uninspect"); diff --git a/src/utils/auto-box-collider.js b/src/utils/auto-box-collider.js index 689c598c682..c6f5e852a2c 100644 --- a/src/utils/auto-box-collider.js +++ b/src/utils/auto-box-collider.js @@ -90,13 +90,13 @@ export const computeObjectAABB = (function () { })(); const rotation = new THREE.Euler(); -export function getBox(entity, boxRoot, worldSpace) { +export function getBox(obj, boxRoot, worldSpace) { const box = new THREE.Box3(); - rotation.copy(entity.object3D.rotation); - entity.object3D.rotation.set(0, 0, 0); + rotation.copy(obj.rotation); + obj.rotation.set(0, 0, 0); - entity.object3D.updateMatrices(true, true); + obj.updateMatrices(true, true); boxRoot.updateMatrices(true, true); boxRoot.updateMatrixWorld(true); @@ -104,11 +104,11 @@ export function getBox(entity, boxRoot, worldSpace) { if (!box.isEmpty()) { if (!worldSpace) { - entity.object3D.worldToLocal(box.min); - entity.object3D.worldToLocal(box.max); + obj.worldToLocal(box.min); + obj.worldToLocal(box.max); } - entity.object3D.rotation.copy(rotation); - entity.object3D.matrixNeedsUpdate = true; + obj.rotation.copy(rotation); + obj.matrixNeedsUpdate = true; } boxRoot.matrixWorldNeedsUpdate = true; diff --git a/src/utils/jsx-entity.ts b/src/utils/jsx-entity.ts index 524a95fca85..f28210286d1 100644 --- a/src/utils/jsx-entity.ts +++ b/src/utils/jsx-entity.ts @@ -38,8 +38,8 @@ import { MaterialTag, VideoTextureSource, Quack, - Mirror, - MixerAnimatableInitialize + MixerAnimatableInitialize, + Inspectable } from "../bit-components"; import { inflateMediaLoader } from "../inflators/media-loader"; import { inflateMediaFrame } from "../inflators/media-frame"; @@ -359,6 +359,7 @@ export interface JSXComponentData extends ComponentData { waypointPreview?: boolean; pdf?: PDFParams; loopAnimation?: LoopAnimationParams; + inspectable?: boolean; } export interface GLTFComponentData extends ComponentData { @@ -464,6 +465,7 @@ const jsxInflators: Required<{ [K in keyof JSXComponentData]: InflatorFn }> = { quack: createDefaultInflator(Quack), mixerAnimatable: createDefaultInflator(MixerAnimatableInitialize), loopAnimation: inflateLoopAnimationInitialize, + inspectable: createDefaultInflator(Inspectable), // inflators that create Object3Ds object3D: addObject3DComponent, slice9: inflateSlice9, diff --git a/src/utils/media-sorting.js b/src/utils/media-sorting.js index 7cf1d440153..f3b237fb996 100644 --- a/src/utils/media-sorting.js +++ b/src/utils/media-sorting.js @@ -1,9 +1,5 @@ -import { faVideo } from "@fortawesome/free-solid-svg-icons/faVideo"; -import { faMusic } from "@fortawesome/free-solid-svg-icons/faMusic"; -import { faImage } from "@fortawesome/free-solid-svg-icons/faImage"; -import { faNewspaper } from "@fortawesome/free-solid-svg-icons/faNewspaper"; -import { faQuestion } from "@fortawesome/free-solid-svg-icons/faQuestion"; -import { faCube } from "@fortawesome/free-solid-svg-icons/faCube"; +import { hasComponent } from "bitecs"; +import { GLTFModel, MediaImage, MediaInfo, MediaPDF, MediaVideo } from "../bit-components"; export const SORT_ORDER_VIDEO = 0; export const SORT_ORDER_AUDIO = 1; @@ -12,7 +8,24 @@ export const SORT_ORDER_PDF = 3; export const SORT_ORDER_MODEL = 4; export const SORT_ORDER_UNIDENTIFIED = 5; -export function mediaSortOrder(el) { +function mediaSortOrder(eid) { + if (hasComponent(APP.world, MediaVideo, eid)) { + if (hasComponent(APP.world, MediaInfo, eid)) { + const contentTypeSid = MediaInfo.contentType[eid]; + const contentType = APP.getString(contentTypeSid); + if (contentType.startsWith("audio/")) { + return SORT_ORDER_AUDIO; + } + } + return SORT_ORDER_VIDEO; + } + if (hasComponent(APP.world, MediaImage, eid)) return SORT_ORDER_IMAGE; + if (hasComponent(APP.world, MediaPDF, eid)) return SORT_ORDER_PDF; + if (hasComponent(APP.world, GLTFModel, eid)) return SORT_ORDER_MODEL; + return SORT_ORDER_UNIDENTIFIED; +} + +function mediaSortOrderAframe(el) { if (el.components["media-video"] && el.components["media-video"].data.contentType.startsWith("audio/")) { return SORT_ORDER_AUDIO; } @@ -23,18 +36,13 @@ export function mediaSortOrder(el) { return SORT_ORDER_UNIDENTIFIED; } -export function mediaSort(el1, el2) { - return mediaSortOrder(el1) - mediaSortOrder(el2); +export function mediaSort(eid1, eid2) { + return mediaSortOrder(eid1) - mediaSortOrder(eid2); } -export const DISPLAY_IMAGE = new Map([ - [SORT_ORDER_VIDEO, faVideo], - [SORT_ORDER_AUDIO, faMusic], - [SORT_ORDER_IMAGE, faImage], - [SORT_ORDER_PDF, faNewspaper], - [SORT_ORDER_UNIDENTIFIED, faQuestion], - [SORT_ORDER_MODEL, faCube] -]); +export function mediaSortAframe(el1, el2) { + return mediaSortOrderAframe(el1) - mediaSortOrderAframe(el2); +} const SORT_ORDER_TO_TYPE = { [SORT_ORDER_VIDEO]: "video", @@ -44,7 +52,12 @@ const SORT_ORDER_TO_TYPE = { [SORT_ORDER_MODEL]: "model" }; -export function getMediaType(el) { - const order = mediaSortOrder(el); +export function getMediaType(eid) { + const order = mediaSortOrder(eid); + return SORT_ORDER_TO_TYPE[order]; +} + +export function getMediaTypeAframe(el) { + const order = mediaSortOrderAframe(el); return SORT_ORDER_TO_TYPE[order]; }