diff --git a/src/bit-systems/behavior-graph/bindings/video.ts b/src/bit-systems/behavior-graph/bindings/video.ts index 5fcef040a6..26576c77b9 100644 --- a/src/bit-systems/behavior-graph/bindings/video.ts +++ b/src/bit-systems/behavior-graph/bindings/video.ts @@ -1,3 +1,4 @@ +import { hasComponent } from "bitecs"; import { HubsWorld } from "../../../app"; import { EntityID, MediaVideo, MediaVideoData, NetworkedVideo } from "../../../bit-components"; import { VIDEO_FLAGS } from "../../../inflators/video"; @@ -6,6 +7,7 @@ import { getProjectionFromProjectionName, getProjectionNameFromProjection } from "../../../utils/projection-mode"; +import { MediaVideoUpdateSrcEvent, updateVideoSrc } from "../../video-system"; export interface GLTFVideoParams { src: string; @@ -27,16 +29,33 @@ export function getVideo(world: HubsWorld, eid: EntityID): GLTFVideoParams { } export function setVideo(world: HubsWorld, eid: EntityID, params: GLTFVideoParams) { - params = Object.assign({}, getVideo(world, eid), params); - if (params.autoPlay) { - NetworkedVideo.flags[eid] |= VIDEO_FLAGS.AUTO_PLAY; + if (params.controls !== undefined) { + if (params.controls) { + NetworkedVideo.flags[eid] |= VIDEO_FLAGS.CONTROLS; + } else { + NetworkedVideo.flags[eid] &= ~VIDEO_FLAGS.CONTROLS; + } } - if (params.loop) { - NetworkedVideo.flags[eid] |= VIDEO_FLAGS.LOOP; + if (params.projection !== undefined) { + NetworkedVideo.projection[eid] = getProjectionFromProjectionName(params.projection); } - if (params.controls) { - NetworkedVideo.flags[eid] |= VIDEO_FLAGS.CONTROLS; + + const video = MediaVideoData.get(eid)!; + let shouldUpdateVideo = false; + if (params.autoPlay !== undefined) { + shouldUpdateVideo ||= video.autoplay !== params.autoPlay; + video.autoplay = params.autoPlay; + } + if (params.loop !== undefined) { + shouldUpdateVideo ||= video.loop !== params.loop; + video.loop = params.loop; + } + let src = video.src; + if (params.src !== undefined) { + shouldUpdateVideo ||= video.src !== params.src; + src = params.src; + } + if (shouldUpdateVideo && !hasComponent(world, MediaVideoUpdateSrcEvent, eid)) { + updateVideoSrc(world, eid, src, video); } - NetworkedVideo.src[eid] = APP.getSid(params.src); - NetworkedVideo.projection[eid] = getProjectionFromProjectionName(params.projection); } diff --git a/src/bit-systems/video-system.ts b/src/bit-systems/video-system.ts index 32bded5b12..132df99eb5 100644 --- a/src/bit-systems/video-system.ts +++ b/src/bit-systems/video-system.ts @@ -32,11 +32,12 @@ import { HubsVideoTexture } from "../textures/HubsVideoTexture"; import { create360ImageMesh, createImageMesh } from "../utils/create-image-mesh"; import { ClearFunction, JobRunner } from "../utils/coroutine-utils"; import { loadVideoTexture } from "../utils/load-video-texture"; -import { resolveMediaInfo } from "../utils/media-utils"; +import { MediaType, resolveMediaInfo } from "../utils/media-utils"; import { swapObject3DComponent } from "../utils/jsx-entity"; import { MediaInfo } from "./media-loading"; import { VIDEO_FLAGS } from "../inflators/video"; import { ProjectionModeName, getProjectionNameFromProjection } from "../utils/projection-mode"; +import { loadAudioTexture } from "../utils/load-audio-texture"; export const MediaVideoUpdateSrcEvent = defineComponent(); @@ -48,11 +49,19 @@ function* loadSrc( clearRollbacks: ClearFunction ) { const projection = getProjectionNameFromProjection(NetworkedVideo.projection[eid]); - const autoPlay = NetworkedVideo.flags[eid] && VIDEO_FLAGS.AUTO_PLAY ? true : false; - const loop = NetworkedVideo.flags[eid] && VIDEO_FLAGS.LOOP ? true : false; - const { accessibleUrl, contentType } = (yield resolveMediaInfo(src)) as MediaInfo; - const { texture, ratio, video }: { texture: HubsVideoTexture; ratio: number; video: HTMLVideoElement } = - yield loadVideoTexture(accessibleUrl, contentType, loop, autoPlay); + const autoPlay = NetworkedVideo.flags[eid] & VIDEO_FLAGS.AUTO_PLAY ? true : false; + const loop = NetworkedVideo.flags[eid] & VIDEO_FLAGS.LOOP ? true : false; + const { accessibleUrl, contentType, mediaType } = (yield resolveMediaInfo(src)) as MediaInfo; + let data: any; + if (mediaType === MediaType.VIDEO) { + data = (yield loadVideoTexture(accessibleUrl, contentType, loop, autoPlay)) as unknown; + } else if (mediaType === MediaType.AUDIO) { + data = (yield loadAudioTexture(accessibleUrl, loop, autoPlay)) as unknown; + } else { + return; + } + + const { texture, ratio, video }: { texture: HubsVideoTexture; ratio: number; video: HTMLVideoElement } = data; clearRollbacks(); // After this point, normal entity cleanup will take care of things @@ -81,7 +90,7 @@ function* loadSrc( swapObject3DComponent(world, eid, videoObj); - if ((NetworkedVideo.flags[eid] & VIDEO_FLAGS.PAUSED) === 0) { + if ((NetworkedVideo.flags[eid] & VIDEO_FLAGS.PAUSED) === 0 || autoPlay) { video.play(); } @@ -154,8 +163,22 @@ export function videoSystem(world: HubsWorld, audioSystem: AudioSystem) { const video = MediaVideoData.get(eid)!; if (hasComponent(world, Owned, eid)) { NetworkedVideo.time[eid] = video.currentTime; - let flags = 0; - flags |= video.paused ? VIDEO_FLAGS.PAUSED : 0; + let flags = NetworkedVideo.flags[eid]; + if (video.paused) { + flags |= VIDEO_FLAGS.PAUSED; + } else { + flags &= ~VIDEO_FLAGS.PAUSED; + } + if (video.loop) { + flags |= VIDEO_FLAGS.LOOP; + } else { + flags &= ~VIDEO_FLAGS.LOOP; + } + if (video.autoplay) { + flags |= VIDEO_FLAGS.AUTO_PLAY; + } else { + flags &= ~VIDEO_FLAGS.AUTO_PLAY; + } NetworkedVideo.flags[eid] = flags; NetworkedVideo.src[eid] = APP.getSid(video.src); } else {