import { _decorator, instantiate, isValid, Label, Node,VideoClip, Sprite, UITransform, Vec3, VideoPlayer, view } from 'cc'; import Utils from '../../Main/Common/Utils'; import { InnerMsgCode } from '../../Main/Config/InnerMsgCode'; import li_BaseView from '../../Main/Common/li_BaseView'; import ResManager from '../../Main/Manager/ResManager'; import GlobalValue, { VideoRoleType } from '../../Main/Common/GlobalValue'; import { SDKManager } from '../../Main/Channel/SDKManager'; import { BgVideo } from '../../Main/Channel/BgVideo'; const { ccclass, property } = _decorator; //场景背景层 - 视频模式 @ccclass('SceneBgVideoLayer') export class SceneBgVideoLayer extends li_BaseView { private _nodeTab: any = {}; private _data; static handle: SceneBgVideoLayer | null = null; private remoteLoopPath: string = "" //远程循环路径 private curVideoType: VideoRoleType = VideoRoleType.None; private sceneBg: Sprite = null; private videoInited: boolean = false; //视频是否初始化完成 private vpWait: BgVideo | null = null; //播表情视频时暂停的背景视频 private emoReady: BgVideo | null = null; //已准备好播放的表情 private videoPlayer: VideoPlayer = null; /**获取videoplayer副本 */ getVideoClone() { let vp = instantiate(this._nodeTab.videoRole) this.node.addChild(vp) let bv = vp.getComponent(BgVideo)! return bv } //----重写父类接口--------------------------------------- onLoadCT() { this.registerListenner(); Utils.parseNode(this.node, this._nodeTab) this.sceneBg = this._nodeTab.sceneBg.getComponent(Sprite)!; this.videoPlayer = this._nodeTab.videoRole.getComponent(VideoPlayer); if (GlobalValue.NpcVideoMod) { this.setVideoInited(true, true) } SceneBgVideoLayer.handle = this; } openUIDataCT(data: any): void { this._data = data } registerListenner() { Utils.addInnerEL(InnerMsgCode.SimplePlayVide,this,this.playLocalLoopVideo); Utils.addInnerEL(InnerMsgCode.SceneLayerBgUp, this, this.resiveBgUp) Utils.addInnerEL(InnerMsgCode.BgVideo_Ready, this, this.resiveBgVideoReady) Utils.addInnerEL(InnerMsgCode.BgVideo_End, this, this.resiveBgVideoEnd) } //刷新场景背景消息 resiveBgUp(data) { if (!GlobalValue.NpcVideoMod) { return } if (data) { if (data.videoPath) { console.log("bgvideo 收到播放视频消息:", data) if (data.videoType == VideoRoleType.Idle) { this.playLoopVideo(data.videoPath, false) } else { this.playOnceVideo(data.videoPath) } } if (!this.videoInited && data.bgPath) { ResManager.I.changeBundleSpriteFrame(this.sceneBg, data.bgPath, "Raw", ()=>{ //调整背景图适配 Utils.adjustBgPixelRatio(this.sceneBg.node, 1) }) } } } /**视频准备好消息 */ resiveBgVideoReady(data:any) { if (!this.videoInited) { this.setVideoInited(true) } if (data.compo) { if (data.compo.vtype == VideoRoleType.emo) { this.setEmoReadyAudio(data.compo) if (this.curVideoType == VideoRoleType.emo) { this.doPlayEmoReadyAudio() } } else if (data.compo.vtype == VideoRoleType.Idle) { this.curVideoType = VideoRoleType.Idle; } } } /**视频播放完毕消息 */ resiveBgVideoEnd(data:any) { if (data.compo) { if (data.compo.vtype == VideoRoleType.emo) { // this.playLoopVideo(this.remoteLoopPath, true) this.doEmoFinish() } else if (data.compo.vtype == VideoRoleType.Idle) { //主视频播完后,检测一下有没有要播的表情视频 if (this.doPlayEmoReadyAudio()) { this.setBgAudioPause(data.compo) } } } } playLocalLoopVideo(data:any) { ResManager.I.changeBundleVideo(this.videoPlayer,data.path,"Chat18x",(res:VideoClip)=>{ this.videoPlayer.play(); // 移除之前的事件监听器,避免重复绑定 this.videoPlayer.node.off(VideoPlayer.EventType.READY_TO_PLAY, this.onVideoReadyToPlay, this); // 添加视频准备完成事件监听 this.videoPlayer.node.on(VideoPlayer.EventType.READY_TO_PLAY, this.onVideoReadyToPlay, this); // 保存当前数据供回调使用 this.currentVideoData = data; // 也立即尝试调整(以防已经准备好) this.adjustVideoToFillFrame(data.size, data.bgFrameNode); }); } private currentVideoData: any = null; private onVideoReadyToPlay = () => { if (this.currentVideoData) { this.adjustVideoToFillFrame(this.currentVideoData.size, this.currentVideoData.bgFrameNode); } } adjustVideoToFillFrame(targetSize: any, bgFrameNode?: Node) { if (!this.videoPlayer) return; const tryAdjust = () => { let uiT: UITransform = this.videoPlayer.node.getComponent(UITransform); const videoSize = uiT.contentSize; console.log('Video size:', videoSize, 'Target size:', targetSize); if (videoSize.width > 0 && videoSize.height > 0) { // 计算宽度和高度的缩放比例 const scaleX = targetSize.width / videoSize.width; const scaleY = targetSize.height / videoSize.height; // 选择较大的缩放比例以填满整个区域(可能超出但不会有黑边) const scale = Math.max(scaleX, scaleY); console.log(`Video scaling: scaleX=${scaleX}, scaleY=${scaleY}, final scale=${scale}`); this.videoPlayer.node.setScale(new Vec3(scale, scale, 1)); // 只有传入bgFrameNode时才调整位置 if (bgFrameNode && isValid(bgFrameNode) && bgFrameNode.position) { this.videoPlayer.node.setPosition( bgFrameNode.position.x, bgFrameNode.position.y, bgFrameNode.position.z ); console.log(`Video positioned to bgFrame center: ${bgFrameNode.position}`); } return true; } return false; }; // 立即尝试一次 if (!tryAdjust()) { // 如果失败,延迟尝试 this.scheduleOnce(() => { if (!tryAdjust()) { // 再次延迟尝试 this.scheduleOnce(() => { tryAdjust(); }, 0.5); } }, 0.1); } } /**播放循环视频 */ playLoopVideo(path: string, force = false) { if (this.remoteLoopPath == path && !force) { return } console.log("bgvideo 播放循环视频", path) this.remoteLoopPath = path SDKManager.PlayBgAudio(path, VideoRoleType.Idle, true) } /**播放单次视频 */ playOnceVideo(path: string) { console.log("bgvideo 播放单次视频", path) SDKManager.AddEmoAudio(path, VideoRoleType.emo, false) } //设置视频是否初始化完成 setVideoInited(inited: boolean, force: boolean = false) { if (this.videoInited == inited && !force) { return } console.log("bgvideo setVideoInited", inited) this.videoInited = inited this._nodeTab.sceneBg.active = !inited } //设置暂停播放的主视频 setBgAudioPause(wait:BgVideo) { console.log("bgvideo 主视频暂停播放") this.vpWait = wait this.vpWait.pauseVideo() } replayBgAudioPause() { console.log("bgvideo 主视频继续播放") if (this.vpWait) { this.vpWait.replayVideo() } } //设置准备好要播放的表情视频 setEmoReadyAudio(au: BgVideo) { console.log("bgvideo 设置ready视频", au) if (this.emoReady) { this.emoReady.recycleVideo() } this.emoReady = au; this.emoReady.pauseVideo() } //移除准备好要播放的表情视频 removeEmoReadyAudio() { console.log("bgvideo 移除ready视频") if (this.emoReady) { this.emoReady.recycleVideo() } this.emoReady = null } //播放准备好要播放的表情视频 doPlayEmoReadyAudio():boolean { if (this.emoReady) { console.log("bgvideo 播放ready视频") this.emoReady.replayVideo() this.emoReady.moveIn() this.curVideoType = VideoRoleType.emo return true } return false } //表情视频播放结束 doEmoFinish() { console.log("bgvideo ready视频播放结束") this.removeEmoReadyAudio() this.replayBgAudioPause() this.curVideoType = VideoRoleType.Idle } }