import { _decorator, isValid, Node, VideoClip, UITransform, Vec3, VideoPlayer, Size, } from "cc"; import Utils from "../../Main/Common/Utils"; import li_BaseView from "../../Main/Common/li_BaseView"; import ResManager from "../../Main/Manager/ResManager"; const { ccclass, property } = _decorator; //场景背景层 - 视频模式 @ccclass("SceneBgVideoLayer") export class SceneBgVideoLayer extends li_BaseView { private _nodeTab: any = {}; private _data; static handle: SceneBgVideoLayer | null = null; private videoPlayer: VideoPlayer = null; private isPlaying: boolean = false; private currentVideoData: any = null; //----重写父类接口--------------------------------------- onLoadCT() { Utils.parseNode(this.node, this._nodeTab); this.videoPlayer = this._nodeTab.videoPlayer.getComponent(VideoPlayer); if (!this.videoPlayer) { console.error("SceneBgVideoLayer: video节点未找到或没有VideoPlayer组件"); } this.initVideoEvents(); SceneBgVideoLayer.handle = this; } openUIDataCT(data: any): void { this._data = data; } /**初始化视频事件监听 */ private initVideoEvents() { if (!this.videoPlayer) return; // 移除之前的事件监听器,避免重复绑定 this.videoPlayer.node.off( VideoPlayer.EventType.READY_TO_PLAY, this.onVideoReadyToPlay, this ); //this.videoPlayer.node.off(VideoPlayer.EventType.VIDEO_PLAYER_EVENT, this.onVideoEvent, this); // 添加新的事件监听 this.videoPlayer.node.on( VideoPlayer.EventType.READY_TO_PLAY, this.onVideoReadyToPlay, this ); // this.videoPlayer.node.on(VideoPlayer.EventType.VIDEO_PLAYER_EVENT, this.onVideoEvent, this); } //================== 公共 API 方法 ================== /** * 播放视频 * @param path 视频路径 * @param loop 是否循环播放 */ playVideo(path: string, loop: boolean = false) { if (!this.videoPlayer) { console.error("SceneBgVideoLayer: VideoPlayer未初始化"); return; } // 加载本地视频资源 ResManager.I.changeBundleVideo( this.videoPlayer, path, "Girls", (res: VideoClip) => { this.videoPlayer.loop = loop; this.videoPlayer.play(); this.isPlaying = true; console.log(`SceneBgVideoLayer: 播放视频 ${path}, 循环: ${loop}`); } ); } /** * 切换视频(停止当前视频并播放新视频) * @param path 视频路径 * @param loop 是否循环播放 */ switchVideo(path: string, loop: boolean = false) { this.stop(); this.playVideo(path, loop); } /** * 暂停视频 */ pause() { if (this.videoPlayer && this.isPlaying) { this.videoPlayer.pause(); console.log("SceneBgVideoLayer: 暂停视频"); } } /** * 继续播放视频 */ resume() { if (this.videoPlayer && !this.videoPlayer.isPlaying) { this.videoPlayer.play(); console.log("SceneBgVideoLayer: 继续播放视频"); } } /** * 停止视频 */ stop() { if (this.videoPlayer) { this.videoPlayer.stop(); this.isPlaying = false; console.log("SceneBgVideoLayer: 停止视频"); } } /** * 设置视频尺寸 * @param width 宽度 * @param height 高度 */ setVideoSize(width: number, height: number) { if (this.videoPlayer) { const uiTransform = this.videoPlayer.node.getComponent(UITransform); if (uiTransform) { uiTransform.setContentSize(width, height); console.log(`SceneBgVideoLayer: 设置视频尺寸 ${width}x${height}`); } } } /** * 设置视频位置 * @param x X坐标 * @param y Y坐标 * @param z Z坐标 */ setVideoPosition(x: number, y: number, z: number = 0) { if (this.videoPlayer) { this.videoPlayer.node.setPosition(x, y, z); console.log(`SceneBgVideoLayer: 设置视频位置 (${x}, ${y}, ${z})`); } } /** * 设置视频世界位置 * @param x X坐标 * @param y Y坐标 * @param z Z坐标 */ setVideoWorldPosition(x: number, y: number, z: number = 0) { if (this.videoPlayer) { this.videoPlayer.node.setWorldPosition(x, y, z); console.log(`SceneBgVideoLayer: 设置视频世界位置 (${x}, ${y}, ${z})`); } } /** * 设置视频锚点 * @param anchorX X轴锚点 (0-1) * @param anchorY Y轴锚点 (0-1) */ setVideoAnchor(anchorX: number, anchorY: number) { if (this.videoPlayer) { const uiTransform = this.videoPlayer.node.getComponent(UITransform); if (uiTransform) { uiTransform.setAnchorPoint(anchorX, anchorY); console.log(`SceneBgVideoLayer: 设置视频锚点 (${anchorX}, ${anchorY})`); } } } /** * 设置视频缩放 * @param scale 缩放值(数字或Vec3) */ setVideoScale(scale: number | Vec3) { if (this.videoPlayer) { if (typeof scale === "number") { this.videoPlayer.node.setScale(new Vec3(scale, scale, 1)); console.log(`SceneBgVideoLayer: 设置视频缩放 ${scale}`); } else { this.videoPlayer.node.setScale(scale); console.log( `SceneBgVideoLayer: 设置视频缩放 (${scale.x}, ${scale.y}, ${scale.z})` ); } } } /** * 调整视频以填满指定区域 * @param targetSize 目标尺寸 * @param position 可选的位置 */ adjustToFillArea(targetSize: Size, position?: Vec3) { if (!this.videoPlayer) return; const tryAdjust = () => { const uiTransform = this.videoPlayer.node.getComponent(UITransform); if (!uiTransform) return false; const videoSize = uiTransform.contentSize; 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); this.videoPlayer.node.setScale(new Vec3(scale, scale, 1)); if (position) { this.videoPlayer.node.setPosition(position); } console.log(`SceneBgVideoLayer: 自适应填充区域,缩放: ${scale}`); return true; } return false; }; // 立即尝试一次 if (!tryAdjust()) { // 如果失败,延迟尝试 this.scheduleOnce(() => { if (!tryAdjust()) { this.scheduleOnce(() => { tryAdjust(); }, 0.5); } }, 0.1); } } //================== 事件回调 ================== private onVideoReadyToPlay = () => { console.log("SceneBgVideoLayer: 视频准备完成"); this.onVideoReady(); }; private onVideoEvent = (event: any, eventType: string) => { switch (eventType) { case "completed": console.log("SceneBgVideoLayer: 视频播放完成"); this.isPlaying = false; this.onVideoEnd(); break; case "error": console.error("SceneBgVideoLayer: 视频播放错误"); this.isPlaying = false; this.onVideoError(); break; } }; /** * 视频准备完成回调(可重写) */ protected onVideoReady() { // 由子类重写或外部监听 } /** * 视频播放完成回调(可重写) */ protected onVideoEnd() { // 由子类重写或外部监听 } /** * 视频播放错误回调(可重写) */ protected onVideoError() { // 由子类重写或外部监听 } //================== 兼容性方法 ================== /** * 播放本地循环视频(保留以保证兼容性) * @deprecated 使用 playVideo(path, true) 替代 */ playLocalLoopVideo(data: any) { if (data?.path) { this.playVideo(data.path, true); // 保存当前数据供回调使用 this.currentVideoData = data; // 如果有尺寸和位置信息,进行调整 if (data.size) { this.adjustToFillArea(data.size, data.bgFrameNode?.position); } } } /** * 调整视频填充框架(保留以保证兼容性) * @deprecated 使用 adjustToFillArea 替代 */ adjustVideoToFillFrame(targetSize: any, bgFrameNode?: Node) { let position: Vec3 | undefined; if (bgFrameNode && isValid(bgFrameNode) && bgFrameNode.position) { position = bgFrameNode.position; } this.adjustToFillArea(targetSize, position); } //================== 其他方法 ================== /** * 获取当前播放状态 */ getIsPlaying(): boolean { return this.isPlaying; } /** * 获取VideoPlayer组件引用 */ getVideoPlayer(): VideoPlayer | null { return this.videoPlayer; } /** * 销毁时清理资源 */ onDestroy() { if (this.videoPlayer) { this.videoPlayer.node.off( VideoPlayer.EventType.READY_TO_PLAY, this.onVideoReadyToPlay, this ); //this.videoPlayer.node.off(VideoPlayer.EventType.VIDEO_PLAYER_EVENT, this.onVideoEvent, this); } SceneBgVideoLayer.handle = null; } }