diff --git a/src/assets/LoadingObject_Atom.glb b/src/assets/LoadingObject_Atom.glb new file mode 100755 index 0000000000000000000000000000000000000000..d00834ee7da5c3f55aa0ec8ff252b704e25f7a28 Binary files /dev/null and b/src/assets/LoadingObject_Atom.glb differ diff --git a/src/assets/environments/environments.js b/src/assets/environments/environments.js index 9bf05b6d13b8cdf97ae6cfff3d7d77def96a2536..74c00f1f125dc202d49127adb29ce87d95bb1db9 100644 --- a/src/assets/environments/environments.js +++ b/src/assets/environments/environments.js @@ -2,7 +2,8 @@ export const ENVIRONMENT_URLS = [ process.env.ASSET_BUNDLE_SERVER + "/rooms/meetingroom/MeetingRoom.bundle.json", process.env.ASSET_BUNDLE_SERVER + "/rooms/atrium/Atrium.bundle.json", process.env.ASSET_BUNDLE_SERVER + "/rooms/MedievalFantasyBook/MedievalFantasyBook.bundle.json", - process.env.ASSET_BUNDLE_SERVER + "/rooms/rooftopbuilding1/RooftopBuilding1.bundle.json" + process.env.ASSET_BUNDLE_SERVER + "/rooms/rooftopbuilding1/RooftopBuilding1.bundle.json", + process.env.ASSET_BUNDLE_SERVER + "/rooms/wideopenspace/WideOpenSpace.bundle.json" ]; export const DEFAULT_ENVIRONMENT_URL = ENVIRONMENT_URLS[0]; diff --git a/src/components/media-loader.js b/src/components/media-loader.js index f505d9c39bf2d7f3065fcdf2c98264f79d186af4..071d1fc4d55f87492171e494f8786bb2657b8da9 100644 --- a/src/components/media-loader.js +++ b/src/components/media-loader.js @@ -1,6 +1,14 @@ import { getBox, getScaleCoefficient } from "../utils/auto-box-collider"; import { resolveMedia, fetchMaxContentIndex } from "../utils/media-utils"; +import "three/examples/js/loaders/GLTFLoader"; +import loadingObjectSrc from "../assets/LoadingObject_Atom.glb"; +const gltfLoader = new THREE.GLTFLoader(); +let loadingObject; +gltfLoader.load(loadingObjectSrc, gltf => { + loadingObject = gltf; +}); + AFRAME.registerComponent("media-loader", { schema: { src: { type: "string" }, @@ -41,6 +49,12 @@ AFRAME.registerComponent("media-loader", { } }, + tick(t, dt) { + if (this.loaderMixer) { + this.loaderMixer.update(dt / 1000); + } + }, + onError() { this.el.removeAttribute("gltf-model-plus"); this.el.removeAttribute("media-pager"); @@ -51,14 +65,26 @@ AFRAME.registerComponent("media-loader", { }, showLoader() { - const loadingObj = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshBasicMaterial()); - this.el.setObject3D("mesh", loadingObj); + const useFancyLoader = !!loadingObject; + const mesh = useFancyLoader + ? loadingObject.scene.clone() + : new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshBasicMaterial()); + if (useFancyLoader) { + this.loaderMixer = new THREE.AnimationMixer(mesh); + this.loadingClip = this.loaderMixer.clipAction(loadingObject.animations[0]); + this.loadingClip.play(); + } + this.el.setObject3D("mesh", mesh); this.setShapeAndScale(true); delete this.showLoaderTimeout; }, clearLoadingTimeout() { clearTimeout(this.showLoaderTimeout); + if (this.loaderMixer) { + this.loadingClip.stop(); + delete this.loaderMixer; + } delete this.showLoaderTimeout; }, diff --git a/src/components/media-views.js b/src/components/media-views.js index a408e8ca646208636156c380cceeedde80e90a59..a6b598eb2684f11dbb0c059b25f9c62f8b54b4c0 100644 --- a/src/components/media-views.js +++ b/src/components/media-views.js @@ -161,6 +161,16 @@ function createImageTexture(url) { }); } +function disposeTexture(texture) { + if (texture.image instanceof HTMLVideoElement) { + const video = texture.image; + video.pause(); + video.src = ""; + video.load(); + } + texture.dispose(); +} + class TextureCache { cache = new Map(); @@ -193,13 +203,7 @@ class TextureCache { // console.log("release", src, cacheItem.count); if (cacheItem.count <= 0) { // Unload the video element to prevent it from continuing to play in the background - if (cacheItem.texture.image instanceof HTMLVideoElement) { - const video = cacheItem.texture.image; - video.pause(); - video.src = ""; - video.load(); - } - cacheItem.texture.dispose(); + disposeTexture(cacheItem.texture); this.cache.delete(src); } } @@ -253,8 +257,12 @@ AFRAME.registerComponent("media-video", { }, remove() { - if (this.data.src) { - textureCache.release(this.data.src); + if (this.mesh && this.mesh.material) { + disposeTexture(this.mesh.material.map); + } + if (this.video) { + this.video.removeEventListener("pause", this.onPauseStateChange); + this.video.removeEventListener("play", this.onPauseStateChange); } }, @@ -265,24 +273,19 @@ AFRAME.registerComponent("media-video", { async updateTexture(src) { let texture; try { - if (textureCache.has(src)) { - texture = textureCache.retain(src); - } else { - texture = await createVideoTexture(src); - texture.audioSource = this.el.sceneEl.audioListener.context.createMediaElementSource(texture.image); - this.video = texture.image; + texture = await createVideoTexture(src); - this.video.addEventListener("pause", this.onPauseStateChange); - this.video.addEventListener("play", this.onPauseStateChange); + // No way to cancel promises, so if src has changed while we were creating the texture just throw it away. + if (this.data.src !== src) { + disposeTexture(texture); + return; + } - textureCache.set(src, texture); + texture.audioSource = this.el.sceneEl.audioListener.context.createMediaElementSource(texture.image); + this.video = texture.image; - // No way to cancel promises, so if src has changed while we were creating the texture just throw it away. - if (this.data.src !== src) { - textureCache.release(src); - return; - } - } + this.video.addEventListener("pause", this.onPauseStateChange); + this.video.addEventListener("play", this.onPauseStateChange); const sound = new THREE.PositionalAudio(this.el.sceneEl.audioListener); sound.setNodeSource(texture.audioSource); @@ -325,12 +328,10 @@ AFRAME.registerComponent("media-video", { if (!src || src === oldData.src) return; - if (this.mesh && this.mesh.map) { + this.remove(); + if (this.mesh && this.mesh.material) { this.mesh.material.map = null; this.mesh.material.needsUpdate = true; - if (this.mesh.map !== errorTexture) { - textureCache.release(oldData.src); - } } this.updateTexture(src); diff --git a/src/gltf-component-mappings.js b/src/gltf-component-mappings.js index 66cc0b95db7624a190e2c02aac6c0e735eae4558..e814ab700b634a19732317e98ccd29bf8df72fe4 100644 --- a/src/gltf-component-mappings.js +++ b/src/gltf-component-mappings.js @@ -9,6 +9,7 @@ AFRAME.GLTFModelPlus.registerComponent("css-class", "css-class"); AFRAME.GLTFModelPlus.registerComponent("scene-shadow", "scene-shadow"); AFRAME.GLTFModelPlus.registerComponent("super-spawner", "super-spawner"); AFRAME.GLTFModelPlus.registerComponent("gltf-model-plus", "gltf-model-plus"); +AFRAME.GLTFModelPlus.registerComponent("media-loader", "media-loader"); AFRAME.GLTFModelPlus.registerComponent("body", "body"); AFRAME.GLTFModelPlus.registerComponent("hide-when-quality", "hide-when-quality"); AFRAME.GLTFModelPlus.registerComponent("light", "light");