设置页、弹窗逻辑、跳转逻辑

视频播放逻辑优化
This commit is contained in:
2025-09-11 00:03:22 +08:00
parent a6b15778a8
commit 7dedbf124c
24 changed files with 2338 additions and 1381 deletions
+109 -40
View File
@@ -7,6 +7,7 @@ import {
Sprite,
UITransform,
VideoPlayer,
Size,
} from "cc";
// 首先加载 polyfills 以确保兼容性
import "../../utils/polyfills";
@@ -27,6 +28,7 @@ import { VideoEmotion, purchase } from "../../../schema/schema";
import { PayToTalkSubpanel } from "./PayToTalkSubpanel";
import { DataId, DataManager } from "../../data/DataManager";
import { GirlData } from "../../data/GirlData";
import { SceneBgVideoLayer } from "../../../Sub/UI/SceneBgVideoLayer";
const { ccclass, property } = _decorator;
@ccclass("ChatPanel")
@@ -46,8 +48,16 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
// @property(Sprite)
// girlImg: Sprite = null;
@property(VideoPlayer)
girlVideo: VideoPlayer = null;
// 移除直接的 VideoPlayer 引用,改用 SceneBgVideoLayer 单例
// @property(VideoPlayer)
// girlVideo: VideoPlayer = null;
@property(UITransform)
videoArea: UITransform = null;
/** 获取 SceneBgVideoLayer 单例实例 */
private get videoLayer(): SceneBgVideoLayer | null {
return SceneBgVideoLayer.handle;
}
@property(ChatContentsLayout)
layout: ChatContentsLayout = null;
@@ -119,17 +129,38 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
this.register();
this.refresh();
this.payToTalkPanel.node.active = false;
// Add video loaded event callback
if (this.girlVideo) {
this.girlVideo.node.on(
VideoPlayer.EventType.READY_TO_PLAY,
() => {
this.adjustVideoScale();
},
this
);
// 检查 SceneBgVideoLayer 是否可用
if (!this.videoLayer) {
console.error("ChatPanel: SceneBgVideoLayer.handle 未初始化");
} else {
console.log("ChatPanel: 成功获取 SceneBgVideoLayer 实例");
this.initVideoPosition();
}
}
/**
* 初始化视频位置和属性
*/
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(
this.videoLayer.node.worldPosition.x,
videoAreaWorldPos.y,
videoAreaWorldPos.z
);
this.videoLayer.setVideoScale(1);
console.log(
`ChatPanel: 初始化视频世界位置到 (${videoAreaWorldPos.x}, ${videoAreaWorldPos.y})`
);
}
register() {
Utils.addInnerEL(
InnerMsgCode.Chat_DialogRefresh,
@@ -179,8 +210,8 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
);
// Cleanup video event listeners
if (this.girlVideo && this.girlVideo.node) {
this.girlVideo.node.off(
if (this.videoLayer && this.videoLayer.node) {
this.videoLayer.node.off(
VideoPlayer.EventType.READY_TO_PLAY,
this.adjustVideoScale,
this
@@ -224,7 +255,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
const chatModel = this.chatController.getChatModel();
// Load initial video based on current emotion
if (this.girlVideo) {
if (this.videoLayer) {
// Get current emotion from ChatController
const currentEmotion = this.chatController.getCurrentEmotion();
console.log(
@@ -241,46 +272,81 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
`Loading initial video: ${initialVideo} (emotion: ${VideoEmotion[initialVideo]})`
);
// 获取 videoArea 的尺寸
const targetSize = this.videoArea
? new Size(this.videoArea.width, this.videoArea.height)
: new Size(600, 800);
const videoData = {
path: initialVideo,
size: targetSize,
bgFrameNode: this.videoArea ? this.videoArea.node : null,
};
// Set current emotion to the loaded video's emotion
this.currentEmotion = this.chatController.getCurrentEmotion();
ResManager.I.changeBundleVideo(this.girlVideo, initialVideo, "Girls");
// Also immediately try to adjust scale (in case already loaded)
this.adjustVideoScale();
this.videoLayer.playLocalLoopVideo(videoData);
// 延迟调整视频缩放
this.scheduleOnce(() => {
this.adjustVideoScale();
}, 0.1);
}
} else {
this.commercialVideos = [];
this.currentEmotion = null; // Reset current emotion when no videos available
console.log("No commercialVideos data available for role", this.id);
console.log("No SceneBgVideoLayer available for role", this.id);
}
}
adjustVideoScale() {
if (!this.girlVideo || !this.girlVideo.node.parent) {
if (!this.videoLayer || !this.videoArea) {
console.error("ChatPanel: SceneBgVideoLayer 或 videoArea 不可用");
return;
}
const tryAdjustScale = () => {
const parentTransform =
this.girlVideo.node.parent.getComponent(UITransform);
const videoTransform = this.girlVideo.node.getComponent(UITransform);
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(
this.videoLayer.node.worldPosition.x,
videoAreaWorldPos.y,
videoAreaWorldPos.z
);
if (parentTransform && videoTransform && videoTransform.height > 0) {
const scale = parentTransform.height / videoTransform.height;
this.girlVideo.node.setScale(scale, scale, 1);
console.log(
`ChatPanel Video scaled to: ${scale}, parent height: ${parentTransform.height}, video height: ${videoTransform.height}`
`ChatPanel: 视频缩放到 ${scale}, videoArea高度: ${this.videoArea.height}, 视频高度: ${videoTransform.height}`
);
console.log(
`ChatPanel: 视频世界位置设置为 (${videoAreaWorldPos.x}, ${videoAreaWorldPos.y})`
);
return true;
}
return false;
};
// Immediately try once
// 立即尝试一次
if (!tryAdjustScale()) {
// If failed, delay and try again
// 如果失败,延迟尝试
this.scheduleOnce(() => {
if (!tryAdjustScale()) {
// Try again with longer delay
// 再次延迟尝试
this.scheduleOnce(() => {
tryAdjustScale();
}, 0.5);
@@ -292,22 +358,28 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
let triggerId = girlData.getTriggerGrilPhotoId(this.categoryId, this.id);
if (triggerId == 0) triggerId = 100040103;
if (triggerId == 0) return;
this.popUpImage.refresh(this.categoryId, this.id, triggerId);
}
setVideoEnable(enable: boolean) {
if (!this.girlVideo) return;
if (!this.videoLayer) {
console.error("ChatPanel: SceneBgVideoLayer 不可用");
return;
}
this.girlVideo.enabled = enable;
if (enable) {
this.girlVideo.play();
this.videoLayer.resume();
console.log("ChatPanel: 恢复视频播放");
} else {
this.videoLayer.pause();
console.log("ChatPanel: 暂停视频播放");
}
}
private switchVideoByEmotion(emotion: VideoEmotion): void {
if (!this.girlVideo) {
if (!this.videoLayer) {
console.warn("Cannot switch video: missing video player");
return;
}
@@ -337,7 +409,8 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
);
// Load the new video
ResManager.I.changeBundleVideo(this.girlVideo, matchingVideo, "Girls");
this.videoLayer.playVideo(matchingVideo, true);
//ResManager.I.changeBundleVideo(this.girlVideo, matchingVideo, "Girls");
// Update current emotion state
this.currentEmotion = emotion;
@@ -357,11 +430,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
`Loading fallback video: ${fallbackVideo} (emotion: ${VideoEmotion[fallbackVideo]})`
);
ResManager.I.changeBundleVideo(
this.girlVideo,
fallbackVideo,
"Chat18x"
);
this.videoLayer.playVideo(fallbackVideo, true);
// Update current emotion state to the fallback video's emotion
this.currentEmotion = this.chatController.getCurrentEmotion();