import { _decorator, Label, Node, Sprite, VideoPlayer, instantiate, UITransform, Size, } from "cc"; import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView"; import ResManager from "db://assets/Scripts/Main/Manager/ResManager"; import { DetailImageItem } from "../../uiitems/DetailImageItem"; import { NavigationManager } from "../../manager/NavigationManager"; import { ConfigManager } from "../../manager/ConfigManager"; import LanguageUtils from "../../../Main/Common/LanguageUtils"; import Utils from "../../../Main/Common/Utils"; import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode"; import { SimpleToggle } from "../components/SimpleToggle"; import { DataManager, DataId } from "../../data/DataManager"; import { GirlData } from "../../data/GirlData"; import { GirlService } from "db://assets/Scripts/chat18x/network/services/GirlService"; import proto from "db://assets/Scripts/proto/proto.pb.js"; import { SceneBgVideoLayer } from "../../../Sub/UI/SceneBgVideoLayer"; const { ccclass, property } = _decorator; @ccclass("GirlDetailPanel") export class GirlDetailPanel extends li_BaseView { @property(UITransform) videoArea: UITransform; // 移除直接的 VideoPlayer 引用,改用 SceneBgVideoLayer 单例 // @property(VideoPlayer) // avatarVideo: VideoPlayer; @property(Label) girlName: Label; /** 获取 SceneBgVideoLayer 单例实例 */ private get videoLayer(): SceneBgVideoLayer | null { return SceneBgVideoLayer.handle; } @property(SimpleToggle) imgToggle: SimpleToggle = null; @property(SimpleToggle) videoToggle: SimpleToggle = null; @property(Node) starParent: Node; @property(Label) tags: Label; @property(Label) descAge: Label; @property(Label) desc: Label; @property(Node) chatBtn: Node; id = 0; @property(DetailImageItem) imgItemInst: DetailImageItem; @property(Node) imgsLayout: Node; openUIDataCT(data) { this.id = data; } onLoadCT() { super.onLoadCT(); this.imgItemInst.node.active = false; this.refresh(this.id); Utils.addInnerEL(InnerMsgCode.LanguageChange, this, () => { this.girlName.string = LanguageUtils.getText(this.nameKey); let desc = ""; const tags = LanguageUtils.getText(this.tagKey).split("|"); for (let i = 0; i < tags.length; i++) { if (i != 0) desc += "\n"; desc += tags[i]; } this.tags.string = desc; this.desc.string = LanguageUtils.getText(this.descKey); }); this.imgToggle.callback = this.bindImgToggle.bind(this); this.videoToggle.callback = this.bindVideoToggle.bind(this); // 检查 SceneBgVideoLayer 是否可用 if (!this.videoLayer) { console.error("GirlDetailPanel: SceneBgVideoLayer.handle 未初始化"); } else { console.log("GirlDetailPanel: 成功获取 SceneBgVideoLayer 实例"); // 初始化视频显示位置 this.initVideoPosition(); } } setVideEnable(enable: boolean) { if (!this.videoLayer) { console.error("GirlDetailPanel: SceneBgVideoLayer 不可用"); return; } if (enable) { // 恢复播放 this.videoLayer.resume(); console.log("GirlDetailPanel: 开启视频播放"); } else { // 暂停播放 this.videoLayer.pause(); console.log("GirlDetailPanel: 暂停视频播放"); } } adjustVideoScale() { if (!this.videoLayer) { console.error("GirlDetailPanel: SceneBgVideoLayer 不可用"); return; } // 获取 videoArea 的尺寸 if (!this.videoArea) { console.error("GirlDetailPanel: videoArea 未设置"); return; } // 参考原有逻辑,计算缩放比例使视频高度填满 videoArea const tryAdjustScale = () => { const videoPlayer = this.videoLayer.getVideoPlayer(); if (!videoPlayer) return false; const videoTransform = videoPlayer.node.getComponent(UITransform); if (videoTransform && videoTransform.height > 0) { // 设置视频锚点为中心 (0.5, 0.5),确保视频的中心点就是定位点 this.videoLayer.setVideoAnchor(0.5, 0.5); // 计算缩放比例,使视频高度填满 videoArea(保持原有逻辑) const scale = this.videoArea.height / videoTransform.height; // 设置视频缩放 this.videoLayer.setVideoScale(scale); // 获取 videoArea 的世界坐标中心点 const videoAreaWorldPos = this.videoArea.node.getWorldPosition(); // 使用世界坐标设置视频位置,确保正确对齐 this.videoLayer.setVideoWorldPosition( videoAreaWorldPos.x, videoAreaWorldPos.y, videoAreaWorldPos.z ); console.log( `GirlDetailPanel: 视频缩放到 ${scale}, videoArea高度: ${this.videoArea.height}, 视频高度: ${videoTransform.height}` ); console.log( `GirlDetailPanel: 视频世界位置设置为 (${videoAreaWorldPos.x}, ${videoAreaWorldPos.y})` ); return true; } return false; }; // 立即尝试一次 if (!tryAdjustScale()) { // 如果失败,延迟尝试(保持原有的重试机制) this.scheduleOnce(() => { if (!tryAdjustScale()) { // 再次延迟尝试 this.scheduleOnce(() => { tryAdjustScale(); }, 0.5); } }, 0.1); } } /** * 获取目标视频尺寸 * 从 videoArea 获取实际需要填充的区域尺寸 */ private getTargetVideoSize(): Size | null { // 从 videoArea 获取目标尺寸 if (this.videoArea) { return new Size(this.videoArea.width, this.videoArea.height); } // 如果没有 videoArea,使用默认尺寸 console.warn("GirlDetailPanel: videoArea 未设置,使用默认尺寸"); return new Size(600, 800); } nameKey: string; tagKey: string; descKey: string; category: number; async refresh(index: number) { const girlData = DataManager.I.getDataById(DataId.Girl); this.category = girlData.getGrilCategoryById(this.id); // 请求详细数据 const reqData = { id: this.id, }; let res = await GirlService.I.reqGetGirlDetail(reqData); if (res && res.code === proto.cs.EnmRetCode.SUCCESS) { // 保存数据 girlData.setGirlDetailData(this.category.toString(), res.data); // 根据数据,刷新界面 this.nameKey = girlData.getGrilName(this.category.toString(), this.id); this.girlName.string = LanguageUtils.getText(this.nameKey); this.descKey = girlData.getGrilDesc(this.category.toString(), this.id); this.desc.string = LanguageUtils.getText(this.descKey); let desc = ""; this.tagKey = girlData.getGrilTagKey(this.category.toString(), this.id); const tags = LanguageUtils.getText(this.tagKey).split("|"); for (let i = 0; i < tags.length; i++) { if (i != 0) desc += "\n"; desc += tags[i]; } this.tags.string = desc; for (let i = 0; i < 5; i++) { this.starParent.children[i].active = i < 5; } let age = girlData.getGrilAge(this.category.toString(), this.id); this.descAge.string = LanguageUtils.getText("girldetailpanel.age") + age.toString(); const firstPath = girlData.getFirstGrilVideoPath( this.category.toString(), this.id ); // 使用 SceneBgVideoLayer 加载并播放视频 if (this.videoLayer && firstPath) { console.log(`GirlDetailPanel: 加载视频 ${firstPath}`); // 获取 videoArea 的尺寸和位置 const targetSize = this.videoArea ? new Size(this.videoArea.width, this.videoArea.height) : new Size(600, 800); // 获取 videoArea 的中心位置作为参考节点 const bgFrameNode = this.videoArea ? this.videoArea.node : null; // 使用 playLocalLoopVideo 方法,保证兼容性 const videoData = { path: firstPath, size: targetSize, bgFrameNode: bgFrameNode, // 传递 videoArea 节点作为位置参考 }; this.videoLayer.playLocalLoopVideo(videoData); // 延迟调整视频缩放和位置,确保视频加载完成 this.scheduleOnce(() => { this.adjustVideoScale(); }, 0.1); } else if (!firstPath) { console.warn( `GirlDetailPanel: 未找到视频路径 category=${this.category}, id=${this.id}` ); } let resIds = girlData.getAllDisplayGrilPhotoId( this.category.toString(), this.id ); this.refreshImgs( proto.cs.EnmResType.ERT_Image, this.category, this.id, resIds ); } } bindImgToggle() { const girlData = DataManager.I.getDataById(DataId.Girl); let resIds = girlData.getAllDisplayGrilPhotoId( this.category.toString(), this.id ); this.refreshImgs( proto.cs.EnmResType.ERT_Image, this.category, this.id, resIds ); } bindVideoToggle() { const girlData = DataManager.I.getDataById(DataId.Girl); let resIds = girlData.getAllDisplayGrilVideoId( this.category.toString(), this.id ); this.refreshImgs( proto.cs.EnmResType.ERT_Video, this.category, this.id, resIds ); } refreshImgs( type: proto.cs.EnmResType, category: number, id: number, resIds: number[] ) { for (let i = this.imgsLayout.children.length - 1; i >= 0; i--) { this.imgsLayout.children[i].destroy(); } let count = resIds.length; for (let i = 0; i < count; i++) { let newNode = instantiate(this.imgItemInst.node); let item = newNode.getComponent(DetailImageItem); let resId = resIds[i]; item.refresh(this, type, category, id, resId); newNode.active = true; this.imgsLayout.addChild(newNode); } } /** * 初始化视频位置和属性 */ private initVideoPosition() { if (!this.videoLayer || !this.videoArea) return; // 设置视频锚点为中心 (0.5, 0.5),这样视频的中心点就是定位点 this.videoLayer.setVideoAnchor(0.5, 0.5); // 使用 videoArea 的世界坐标位置 const videoAreaWorldPos = this.videoArea.node.getWorldPosition(); this.videoLayer.setVideoWorldPosition( videoAreaWorldPos.x, videoAreaWorldPos.y, videoAreaWorldPos.z ); this.videoLayer.setVideoScale(1); console.log( `GirlDetailPanel: 初始化视频世界位置到 (${videoAreaWorldPos.x}, ${videoAreaWorldPos.y})` ); } OnClickChatBtn() { // 使用带过渡动画的导航方法 NavigationManager.Instance.navigateToChatWithTransition( this.category.toString(), this.id, this ); // 注意:不在这里直接调用onClose,而是在动画完成后由NavigationManager调用 } returnBtn() { this.onClose(); NavigationManager.Instance.navigateToGirlList(this.category); //ViewManager.I.openBundlesView("GirlListPanel"); } /** * 面板关闭时的清理工作 */ onClose() { // 停止视频播放,释放资源 if (this.videoLayer) { //this.videoLayer.stop(); //console.log("GirlDetailPanel: 停止视频播放"); } super.onClose(); } /** * 面板销毁时的清理工作 */ onDestroy() { // 确保视频资源被释放 if (this.videoLayer) { //this.videoLayer.stop(); //console.log("GirlDetailPanel: 销毁时停止视频播放"); } super.onDestroy(); } }