import { _decorator, Label, Node, Sprite, VideoPlayer, instantiate, UITransform, Size, Vec3, tween, } 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; @property(Node) descContent: Node; id = 0; @property(DetailImageItem) imgItemInst: DetailImageItem; @property(Node) imgsLayout: Node; openUIDataCT(data) { this.id = data; } videoAreaPos; onLoadCT() { super.onLoadCT(); this.imgItemInst.node.active = false; this.videoAreaPos = new Vec3(540, 1384); const pos = new Vec3( this.descContent.position.x, this.descContent.position.y, this.descContent.position.z ); this.descContent.position = new Vec3(pos.x, pos.y - 1000, pos.z); //this.node.scale = Vec3.ZERO; tween(this.descContent) .to(0.3, { position: pos }, { easing: "quadOut" }) .start(); // 检查 SceneBgVideoLayer 是否可用 if (!this.videoLayer) { console.error("GirlDetailPanel: SceneBgVideoLayer.handle 未初始化"); } else { console.log("GirlDetailPanel: 成功获取 SceneBgVideoLayer 实例"); // 初始化视频显示位置 //this.initVideoPosition(); } 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); } 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: 暂停视频播放"); } } /** * 获取目标视频尺寸 * 从 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 videoAreaPos = this.videoAreaPos; if (this.videoArea) { // 获取 videoArea 的世界坐标 this.videoAreaPos = this.videoArea.node.getWorldPosition(); // 也检查 videoLayer 的父节点信息,确保坐标系统一致 if (this.videoLayer && this.videoLayer.getVideoPlayer()) { const videoPlayerParent = this.videoLayer.getVideoPlayer().node.parent; if (videoPlayerParent) { const parentWorldPos = videoPlayerParent.getWorldPosition(); console.log( `GirlDetailPanel: VideoPlayer 父节点世界位置: (${parentWorldPos.x}, ${parentWorldPos.y}, ${parentWorldPos.z})` ); } } } // 使用新的统一 playVideo 方法 this.videoLayer.playVideo(firstPath, { loop: true, size: targetSize, position: videoAreaPos, }); } 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; // 使用 videoArea 的世界坐标位置 const videoAreaWorldPos = this.videoArea.node.getWorldPosition(); // 视频位置和缩放已在 playVideo 中处理 //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(); } }