This commit is contained in:
2025-09-11 10:54:06 +08:00
parent 53f2037c49
commit a590433a91
7 changed files with 413 additions and 419 deletions
+35 -84
View File
@@ -23,7 +23,7 @@
"_active": true, "_active": true,
"_components": [], "_components": [],
"_prefab": { "_prefab": {
"__id__": 26 "__id__": 24
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -54,7 +54,7 @@
}, },
"autoReleaseAssets": false, "autoReleaseAssets": false,
"_globals": { "_globals": {
"__id__": 27 "__id__": 25
}, },
"_id": "1a23cd3e-e487-4fd1-a415-346c2087464d" "_id": "1a23cd3e-e487-4fd1-a415-346c2087464d"
}, },
@@ -74,25 +74,25 @@
"__id__": 5 "__id__": 5
}, },
{ {
"__id__": 16 "__id__": 14
}, },
{ {
"__id__": 19 "__id__": 17
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{
"__id__": 20
},
{
"__id__": 21
},
{ {
"__id__": 22 "__id__": 22
}, },
{ {
"__id__": 23 "__id__": 23
},
{
"__id__": 24
},
{
"__id__": 25
} }
], ],
"_prefab": null, "_prefab": null,
@@ -231,17 +231,14 @@
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{
"__id__": 11
},
{ {
"__id__": 12 "__id__": 12
}, },
{ {
"__id__": 13 "__id__": 13
},
{
"__id__": 14
},
{
"__id__": 15
} }
], ],
"_prefab": null, "_prefab": null,
@@ -292,10 +289,7 @@
"__id__": 8 "__id__": 8
}, },
{ {
"__id__": 9 "__id__": 10
},
{
"__id__": 11
} }
], ],
"_prefab": null, "_prefab": null,
@@ -340,8 +334,8 @@
"__prefab": null, "__prefab": null,
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 361, "width": 384,
"height": 384 "height": 672
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -350,36 +344,6 @@
}, },
"_id": "e9cMt7vAhIc4a7k9vEIMWF" "_id": "e9cMt7vAhIc4a7k9vEIMWF"
}, },
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 6
},
"_enabled": true,
"__prefab": null,
"_alignFlags": 45,
"_target": null,
"_left": 359.5,
"_right": 359.5,
"_top": 978,
"_bottom": 978,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 100,
"_originalHeight": 100,
"_alignMode": 2,
"_lockFlags": 0,
"_id": "2euXGGuaZBbJIjbeaF9ka3"
},
{ {
"__type__": "cc.VideoPlayer", "__type__": "cc.VideoPlayer",
"_name": "", "_name": "",
@@ -403,7 +367,7 @@
"_keepAspectRatio": true, "_keepAspectRatio": true,
"videoPlayerEvent": [ "videoPlayerEvent": [
{ {
"__id__": 10 "__id__": 9
} }
], ],
"_id": "4eO0OJtSRAuJxLXluDHDbn" "_id": "4eO0OJtSRAuJxLXluDHDbn"
@@ -482,19 +446,6 @@
"_lockFlags": 0, "_lockFlags": 0,
"_id": "88uIpLSUpFcq1yB9nA16Xu" "_id": "88uIpLSUpFcq1yB9nA16Xu"
}, },
{
"__type__": "f681beDEhFI370t373WShvI",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 5
},
"_enabled": true,
"__prefab": null,
"m_rootNode": null,
"_id": "e4rzfSu/JJyaeVTZFmKOUc"
},
{ {
"__type__": "5caf8//TmZHLJgls9ahUjBU", "__type__": "5caf8//TmZHLJgls9ahUjBU",
"_name": "", "_name": "",
@@ -520,10 +471,10 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 17 "__id__": 15
}, },
{ {
"__id__": 18 "__id__": 16
} }
], ],
"_prefab": null, "_prefab": null,
@@ -562,7 +513,7 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 16 "__id__": 14
}, },
"_enabled": true, "_enabled": true,
"__prefab": null, "__prefab": null,
@@ -584,7 +535,7 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 16 "__id__": 14
}, },
"_enabled": true, "_enabled": true,
"__prefab": null, "__prefab": null,
@@ -620,10 +571,10 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 20 "__id__": 18
}, },
{ {
"__id__": 21 "__id__": 19
} }
], ],
"_prefab": null, "_prefab": null,
@@ -662,7 +613,7 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 19 "__id__": 17
}, },
"_enabled": true, "_enabled": true,
"__prefab": null, "__prefab": null,
@@ -684,7 +635,7 @@
"_objFlags": 0, "_objFlags": 0,
"__editorExtras__": {}, "__editorExtras__": {},
"node": { "node": {
"__id__": 19 "__id__": 17
}, },
"_enabled": true, "_enabled": true,
"__prefab": null, "__prefab": null,
@@ -787,10 +738,10 @@
"_enabled": true, "_enabled": true,
"__prefab": null, "__prefab": null,
"UIRoot": { "UIRoot": {
"__id__": 16 "__id__": 14
}, },
"UILayerMod": { "UILayerMod": {
"__id__": 19 "__id__": 17
}, },
"MainCamera": { "MainCamera": {
"__id__": 4 "__id__": 4
@@ -808,28 +759,28 @@
{ {
"__type__": "cc.SceneGlobals", "__type__": "cc.SceneGlobals",
"ambient": { "ambient": {
"__id__": 28 "__id__": 26
}, },
"shadows": { "shadows": {
"__id__": 29 "__id__": 27
}, },
"_skybox": { "_skybox": {
"__id__": 30 "__id__": 28
}, },
"fog": { "fog": {
"__id__": 31 "__id__": 29
}, },
"octree": { "octree": {
"__id__": 32 "__id__": 30
}, },
"skin": { "skin": {
"__id__": 33 "__id__": 31
}, },
"lightProbeInfo": { "lightProbeInfo": {
"__id__": 34 "__id__": 32
}, },
"postSettings": { "postSettings": {
"__id__": 35 "__id__": 33
}, },
"bakedWithStationaryMainLight": false, "bakedWithStationaryMainLight": false,
"bakedWithHighpLightmap": false "bakedWithHighpLightmap": false
+93 -104
View File
@@ -63,40 +63,117 @@ export class SceneBgVideoLayer extends li_BaseView {
//================== 公共 API 方法 ================== //================== 公共 API 方法 ==================
/** /**
* 播放视频 * 播放视频 - 统一的视频播放接口
* @param path 视频路径 * @param path 视频路径
* @param loop 是否循环播放 * @param options 可选配置项
* @param options.loop 是否循环播放,默认true
* @param options.size 视频尺寸 {width, height}
* @param options.position 视频位置 {x, y, z}
* @param options.scale 视频缩放值
* @param options.autoFill 是否自动填充到指定尺寸
*/ */
playVideo(path: string, loop: boolean = false) { playVideo(
path: string,
options?: {
loop?: boolean;
size?: { width: number; height: number } | Size;
position?: { x: number; y: number; z?: number } | Vec3;
scale?: number | Vec3;
}
) {
if (!this.videoPlayer) { if (!this.videoPlayer) {
console.error("SceneBgVideoLayer: VideoPlayer未初始化"); console.error("SceneBgVideoLayer: VideoPlayer未初始化");
return; return;
} }
// 默认参数
const config = {
loop: options?.loop ?? true,
size: options?.size,
position: options?.position,
scale: options?.scale,
};
// 先停止当前视频
if (this.isPlaying) {
this.stop();
}
// 加载本地视频资源 // 加载本地视频资源
ResManager.I.changeBundleVideo( ResManager.I.changeBundleVideo(
this.videoPlayer, this.videoPlayer,
path, path,
"Girls", "Girls",
(res: VideoClip) => { (res: VideoClip) => {
this.videoPlayer.loop = loop; this.videoPlayer.loop = config.loop;
// 设置锚点为中心,确保位置对齐
const uiTransform = this.videoPlayer.node.getComponent(UITransform);
if (uiTransform) {
uiTransform.setAnchorPoint(0.5, 0.5);
}
// 应用位置设置(使用世界坐标)
if (config.position) {
const pos = config.position;
if (pos instanceof Vec3) {
this.videoPlayer.node.setWorldPosition(pos);
} else {
this.videoPlayer.node.setWorldPosition(pos.x, pos.y, pos.z || 0);
}
}
// 如果传入了目标尺寸,计算并应用缩放
if (config.size && uiTransform) {
// 获取视频的原始尺寸
const videoWidth = uiTransform.contentSize.width;
const videoHeight = uiTransform.contentSize.height;
if (videoWidth > 0 && videoHeight > 0) {
const targetWidth = config.size instanceof Size ? config.size.width : config.size.width;
const targetHeight = config.size instanceof Size ? config.size.height : config.size.height;
// 计算缩放比例(填满整个区域)
const scaleX = targetWidth / videoWidth;
const scaleY = targetHeight / videoHeight;
const scale = Math.max(scaleX, scaleY);
this.videoPlayer.node.setScale(new Vec3(scale, scale, 1));
console.log(`SceneBgVideoLayer: 视频原始尺寸: ${videoWidth}x${videoHeight}, 目标尺寸: ${targetWidth}x${targetHeight}, 缩放: ${scale}`);
} else {
// 如果视频尺寸还未准备好,延迟重试
this.scheduleOnce(() => {
if (config.size && uiTransform) {
const videoWidth = uiTransform.contentSize.width;
const videoHeight = uiTransform.contentSize.height;
if (videoWidth > 0 && videoHeight > 0) {
const targetWidth = config.size instanceof Size ? config.size.width : config.size.width;
const targetHeight = config.size instanceof Size ? config.size.height : config.size.height;
const scaleX = targetWidth / videoWidth;
const scaleY = targetHeight / videoHeight;
const scale = Math.max(scaleX, scaleY);
this.videoPlayer.node.setScale(new Vec3(scale, scale, 1));
console.log(`SceneBgVideoLayer: (延迟) 视频原始尺寸: ${videoWidth}x${videoHeight}, 目标尺寸: ${targetWidth}x${targetHeight}, 缩放: ${scale}`);
}
}
}, 0.1);
}
}
// 如果显式传入了 scale 参数,覆盖自动计算的缩放
else if (config.scale !== undefined) {
this.setVideoScale(config.scale);
}
this.videoPlayer.play(); this.videoPlayer.play();
this.isPlaying = true; this.isPlaying = true;
console.log(`SceneBgVideoLayer: 播放视频 ${path}, 循环: ${loop}`); console.log(`SceneBgVideoLayer: 播放视频 ${path}, 配置:`, config);
} }
); );
} }
/**
* 切换视频(停止当前视频并播放新视频)
* @param path 视频路径
* @param loop 是否循环播放
*/
switchVideo(path: string, loop: boolean = false) {
this.stop();
this.playVideo(path, loop);
}
/** /**
* 暂停视频 * 暂停视频
*/ */
@@ -128,62 +205,6 @@ export class SceneBgVideoLayer extends li_BaseView {
} }
} }
/**
* 设置视频尺寸
* @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 * @param scale 缩放值(数字或Vec3
@@ -227,7 +248,7 @@ export class SceneBgVideoLayer extends li_BaseView {
this.videoPlayer.node.setScale(new Vec3(scale, scale, 1)); this.videoPlayer.node.setScale(new Vec3(scale, scale, 1));
if (position) { if (position) {
this.videoPlayer.node.setPosition(position); this.videoPlayer.node.setWorldPosition(position);
} }
console.log(`SceneBgVideoLayer: 自适应填充区域,缩放: ${scale}`); console.log(`SceneBgVideoLayer: 自适应填充区域,缩放: ${scale}`);
@@ -292,38 +313,6 @@ export class SceneBgVideoLayer extends li_BaseView {
// 由子类重写或外部监听 // 由子类重写或外部监听
} }
//================== 兼容性方法 ==================
/**
* 播放本地循环视频(保留以保证兼容性)
* @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);
}
//================== 其他方法 ================== //================== 其他方法 ==================
/** /**
+40 -42
View File
@@ -135,32 +135,9 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
console.error("ChatPanel: SceneBgVideoLayer.handle 未初始化"); console.error("ChatPanel: SceneBgVideoLayer.handle 未初始化");
} else { } else {
console.log("ChatPanel: 成功获取 SceneBgVideoLayer 实例"); 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() { register() {
Utils.addInnerEL( Utils.addInnerEL(
InnerMsgCode.Chat_DialogRefresh, InnerMsgCode.Chat_DialogRefresh,
@@ -277,15 +254,18 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
? new Size(this.videoArea.width, this.videoArea.height) ? new Size(this.videoArea.width, this.videoArea.height)
: new Size(600, 800); : 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 // Set current emotion to the loaded video's emotion
this.currentEmotion = this.chatController.getCurrentEmotion(); this.currentEmotion = this.chatController.getCurrentEmotion();
this.videoLayer.playLocalLoopVideo(videoData);
// 使用新的统一 playVideo 方法
const videoAreaPos = this.videoArea
? this.videoArea.node.getWorldPosition()
: undefined;
this.videoLayer.playVideo(initialVideo, {
loop: true,
size: targetSize,
position: videoAreaPos,
});
// 延迟调整视频缩放 // 延迟调整视频缩放
this.scheduleOnce(() => { this.scheduleOnce(() => {
@@ -311,9 +291,6 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
const videoTransform = videoPlayer.node.getComponent(UITransform); const videoTransform = videoPlayer.node.getComponent(UITransform);
if (videoTransform && videoTransform.height > 0) { if (videoTransform && videoTransform.height > 0) {
// 设置视频锚点为中心 (0.5, 0.5),确保视频的中心点就是定位点
this.videoLayer.setVideoAnchor(0.5, 0.5);
// 计算缩放比例,使视频高度填满 videoArea // 计算缩放比例,使视频高度填满 videoArea
const scale = this.videoArea.height / videoTransform.height; const scale = this.videoArea.height / videoTransform.height;
@@ -323,12 +300,9 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
// 获取 videoArea 的世界坐标中心点 // 获取 videoArea 的世界坐标中心点
const videoAreaWorldPos = this.videoArea.node.getWorldPosition(); const videoAreaWorldPos = this.videoArea.node.getWorldPosition();
// 使用世界坐标设置视频位置,确保正确对齐 // 使用新的 playVideo 方法的位置参数,如果需要更新位置
this.videoLayer.setVideoWorldPosition( // 由于视频已经在播放,这里只调整缩放
this.videoLayer.node.worldPosition.x, // 位置调整已在 playVideo 中处理
videoAreaWorldPos.y,
videoAreaWorldPos.z
);
console.log( console.log(
`ChatPanel: 视频缩放到 ${scale}, videoArea高度: ${this.videoArea.height}, 视频高度: ${videoTransform.height}` `ChatPanel: 视频缩放到 ${scale}, videoArea高度: ${this.videoArea.height}, 视频高度: ${videoTransform.height}`
@@ -408,8 +382,20 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
})` })`
); );
// Load the new video // Load the new video with the unified playVideo method
this.videoLayer.playVideo(matchingVideo, true); // 获取 videoArea 的尺寸和位置
const targetSize = this.videoArea
? new Size(this.videoArea.width, this.videoArea.height)
: new Size(600, 800);
const videoAreaPos = this.videoArea
? this.videoArea.node.getWorldPosition()
: undefined;
this.videoLayer.playVideo(matchingVideo, {
loop: true,
size: targetSize,
position: videoAreaPos,
});
//ResManager.I.changeBundleVideo(this.girlVideo, matchingVideo, "Girls"); //ResManager.I.changeBundleVideo(this.girlVideo, matchingVideo, "Girls");
// Update current emotion state // Update current emotion state
@@ -430,7 +416,19 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
`Loading fallback video: ${fallbackVideo} (emotion: ${VideoEmotion[fallbackVideo]})` `Loading fallback video: ${fallbackVideo} (emotion: ${VideoEmotion[fallbackVideo]})`
); );
this.videoLayer.playVideo(fallbackVideo, true); // 获取 videoArea 的尺寸和位置
const targetSize = this.videoArea
? new Size(this.videoArea.width, this.videoArea.height)
: new Size(600, 800);
const videoAreaPos = this.videoArea
? this.videoArea.node.getWorldPosition()
: undefined;
this.videoLayer.playVideo(fallbackVideo, {
loop: true,
size: targetSize,
position: videoAreaPos,
});
// Update current emotion state to the fallback video's emotion // Update current emotion state to the fallback video's emotion
this.currentEmotion = this.chatController.getCurrentEmotion(); this.currentEmotion = this.chatController.getCurrentEmotion();
@@ -73,6 +73,16 @@ export class GirlDetailPanel extends li_BaseView {
onLoadCT() { onLoadCT() {
super.onLoadCT(); super.onLoadCT();
this.imgItemInst.node.active = false; this.imgItemInst.node.active = false;
// 检查 SceneBgVideoLayer 是否可用
if (!this.videoLayer) {
console.error("GirlDetailPanel: SceneBgVideoLayer.handle 未初始化");
} else {
console.log("GirlDetailPanel: 成功获取 SceneBgVideoLayer 实例");
// 初始化视频显示位置
this.initVideoPosition();
}
this.refresh(this.id); this.refresh(this.id);
Utils.addInnerEL(InnerMsgCode.LanguageChange, this, () => { Utils.addInnerEL(InnerMsgCode.LanguageChange, this, () => {
@@ -89,15 +99,6 @@ export class GirlDetailPanel extends li_BaseView {
this.imgToggle.callback = this.bindImgToggle.bind(this); this.imgToggle.callback = this.bindImgToggle.bind(this);
this.videoToggle.callback = this.bindVideoToggle.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) { setVideEnable(enable: boolean) {
@@ -117,69 +118,6 @@ export class GirlDetailPanel extends li_BaseView {
} }
} }
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 获取实际需要填充的区域尺寸 * 从 videoArea 获取实际需要填充的区域尺寸
@@ -244,25 +182,17 @@ export class GirlDetailPanel extends li_BaseView {
? new Size(this.videoArea.width, this.videoArea.height) ? new Size(this.videoArea.width, this.videoArea.height)
: new Size(600, 800); : new Size(600, 800);
// 获取 videoArea 的中心位置作为参考节点 // 获取 videoArea 的中心位置作为参考节点(使用世界坐标)
const bgFrameNode = this.videoArea ? this.videoArea.node : null; const videoAreaPos = this.videoArea
? this.videoArea.node.getWorldPosition()
: undefined;
// 使用 playLocalLoopVideo 方法,保证兼容性 // 使用新的统一 playVideo 方法
const videoData = { this.videoLayer.playVideo(firstPath, {
path: firstPath, loop: true,
size: targetSize, size: targetSize,
bgFrameNode: bgFrameNode, // 传递 videoArea 节点作为位置参考 position: videoAreaPos
}; });
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( let resIds = girlData.getAllDisplayGrilPhotoId(
@@ -333,16 +263,9 @@ export class GirlDetailPanel extends li_BaseView {
private initVideoPosition() { private initVideoPosition() {
if (!this.videoLayer || !this.videoArea) return; if (!this.videoLayer || !this.videoArea) return;
// 设置视频锚点为中心 (0.5, 0.5),这样视频的中心点就是定位点
this.videoLayer.setVideoAnchor(0.5, 0.5);
// 使用 videoArea 的世界坐标位置 // 使用 videoArea 的世界坐标位置
const videoAreaWorldPos = this.videoArea.node.getWorldPosition(); const videoAreaWorldPos = this.videoArea.node.getWorldPosition();
this.videoLayer.setVideoWorldPosition( // 视频位置和缩放已在 playVideo 中处理
videoAreaWorldPos.x,
videoAreaWorldPos.y,
videoAreaWorldPos.z
);
this.videoLayer.setVideoScale(1); this.videoLayer.setVideoScale(1);
console.log( console.log(
`GirlDetailPanel: 初始化视频世界位置到 (${videoAreaWorldPos.x}, ${videoAreaWorldPos.y})` `GirlDetailPanel: 初始化视频世界位置到 (${videoAreaWorldPos.x}, ${videoAreaWorldPos.y})`
+71 -42
View File
@@ -5,13 +5,17 @@ import {
Sprite, Sprite,
UITransform, UITransform,
VideoPlayer, VideoPlayer,
VideoClip,
view, view,
Size,
Vec3,
} from "cc"; } from "cc";
import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView"; import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView";
import ResManager from "db://assets/Scripts/Main/Manager/ResManager"; import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
import Utils from "db://assets/Scripts/Main/Common/Utils"; import Utils from "db://assets/Scripts/Main/Common/Utils";
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager"; import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
import { GButton } from "db://assets/Scripts/Main/Common/GButton"; import { GButton } from "db://assets/Scripts/Main/Common/GButton";
import { SceneBgVideoLayer } from "../../../Sub/UI/SceneBgVideoLayer";
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
interface ShowPanelData { interface ShowPanelData {
@@ -26,6 +30,8 @@ export class ShowPanel extends li_BaseView {
image: Sprite; image: Sprite;
@property(Sprite) @property(Sprite)
splash: Sprite; splash: Sprite;
@property(UITransform)
videoArea: UITransform;
@property(VideoPlayer) @property(VideoPlayer)
videoPlayer: VideoPlayer; videoPlayer: VideoPlayer;
@@ -41,15 +47,6 @@ export class ShowPanel extends li_BaseView {
onLoadCT() { onLoadCT() {
this.show(this.url); this.show(this.url);
// 添加视频加载完成回调
this.videoPlayer.node.on(
VideoPlayer.EventType.READY_TO_PLAY,
() => {
this.adjustVideoScale();
},
this
);
} }
start() { start() {
@@ -58,6 +55,11 @@ export class ShowPanel extends li_BaseView {
} }
protected onClose() { protected onClose() {
// 停止视频播放
if (this.videoPlayer) {
this.videoPlayer.stop();
}
if (this.func) { if (this.func) {
this.func(); this.func();
} }
@@ -70,42 +72,69 @@ export class ShowPanel extends li_BaseView {
Utils.adjustBgPixelRatio(this.image.node, 3); Utils.adjustBgPixelRatio(this.image.node, 3);
}); });
} else { } else {
ResManager.I.changeBundleVideo(this.videoPlayer, path, "Girls", () => { // 使用自己的 videoPlayer 进行置顶显示
this.adjustVideoScale(); if (this.videoPlayer) {
}); const targetSize = this.videoArea
? new Size(this.videoArea.width, this.videoArea.height)
: new Size(600, 800);
ResManager.I.changeBundleVideo(
this.videoPlayer,
path,
"Girls",
(res: VideoClip) => {
// 设置视频大小和位置
const uiTransform = this.videoPlayer.node.getComponent(UITransform);
if (uiTransform && this.videoArea) {
uiTransform.setContentSize(targetSize.width, targetSize.height);
// 设置位置为 videoArea 的位置
const pos = this.videoArea.node.getWorldPosition();
this.videoPlayer.node.setWorldPosition(pos);
}
this.videoPlayer.loop = true;
this.videoPlayer.play();
// 延迟调整缩放以填充区域
this.scheduleOnce(() => {
this.adjustVideoScale();
}, 0.1);
}
);
} else {
// 如果没有配置 videoPlayer,使用 SceneBgVideoLayer 作为后备
const targetSize = this.videoArea
? new Size(this.videoArea.width, this.videoArea.height)
: new Size(600, 800);
const videoAreaPos = this.videoArea
? this.videoArea.node.getWorldPosition()
: undefined;
if (SceneBgVideoLayer.handle) {
SceneBgVideoLayer.handle.playVideo(path, {
loop: true,
size: targetSize,
position: videoAreaPos,
});
}
}
} }
} }
adjustVideoScale() { /**
if (!this.videoPlayer) { * 调整视频缩放以填满区域
return; */
} private adjustVideoScale() {
if (!this.videoPlayer || !this.videoArea) return;
const tryAdjustScale = () => {
const screenSize = view.getVisibleSize(); const videoTransform = this.videoPlayer.node.getComponent(UITransform);
if (videoTransform && videoTransform.height > 0) {
const videoTransform = this.videoPlayer.node.getComponent(UITransform); const scaleX = this.videoArea.width / videoTransform.width;
const scaleY = this.videoArea.height / videoTransform.height;
if (videoTransform && videoTransform.height > 0) { const scale = Math.max(scaleX, scaleY); // 填满整个区域
let scale = screenSize.width / videoTransform.width;
this.videoPlayer.node.setScale(scale, scale, 1); this.videoPlayer.node.setScale(new Vec3(scale, scale, 1));
console.log(`ShowPanel: 调整视频缩放到 ${scale}`);
return true;
}
return false;
};
// 立即尝试一次
if (!tryAdjustScale()) {
// 如果失败,延迟尝试
this.scheduleOnce(() => {
if (!tryAdjustScale()) {
// 再次延迟尝试
this.scheduleOnce(() => {
tryAdjustScale();
}, 0.5);
}
}, 0.1);
} }
} }
} }
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "f24940a7-d618-4ee2-a6b9-8ba05b2fe267",
"files": [],
"subMetas": {},
"userData": {}
}
+145 -50
View File
@@ -30,18 +30,18 @@
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{
"__id__": 24
},
{
"__id__": 26
},
{ {
"__id__": 28 "__id__": 28
},
{
"__id__": 30
},
{
"__id__": 32
} }
], ],
"_prefab": { "_prefab": {
"__id__": 30 "__id__": 34
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -447,18 +447,19 @@
"_parent": { "_parent": {
"__id__": 1 "__id__": 1
}, },
"_children": [], "_children": [
{
"__id__": 19
}
],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 19 "__id__": 25
},
{
"__id__": 21
} }
], ],
"_prefab": { "_prefab": {
"__id__": 23 "__id__": 27
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
@@ -489,6 +490,127 @@
}, },
"_id": "" "_id": ""
}, },
{
"__type__": "cc.Node",
"_name": "VideoPlayer",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 18
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 20
},
{
"__id__": 22
}
],
"_prefab": {
"__id__": 24
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 33554432,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 19
},
"_enabled": true,
"__prefab": {
"__id__": 21
},
"_contentSize": {
"__type__": "cc.Size",
"width": 384,
"height": 672
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "a4dlzYsPlE4J4+Ej16vdWP"
},
{
"__type__": "cc.VideoPlayer",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 19
},
"_enabled": true,
"__prefab": {
"__id__": 23
},
"_resourceType": 1,
"_remoteURL": "",
"_clip": null,
"_playOnAwake": true,
"_volume": 1,
"_mute": false,
"_playbackRate": 1,
"_loop": false,
"_fullScreenOnAwake": false,
"_stayOnBottom": false,
"_keepAspectRatio": true,
"videoPlayerEvent": [],
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "104U4SIi9J9oUdCdMtQN8I"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "11zQc04etBLK2ie+tkWM3R",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{ {
"__type__": "cc.UITransform", "__type__": "cc.UITransform",
"_name": "", "_name": "",
@@ -499,12 +621,12 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 20 "__id__": 26
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 1170, "width": 450,
"height": 2532 "height": 695.5
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -517,36 +639,6 @@
"__type__": "cc.CompPrefabInfo", "__type__": "cc.CompPrefabInfo",
"fileId": "adE8tlqHhN2YnsHttPJDRn" "fileId": "adE8tlqHhN2YnsHttPJDRn"
}, },
{
"__type__": "cc.VideoPlayer",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 18
},
"_enabled": true,
"__prefab": {
"__id__": 22
},
"_resourceType": 1,
"_remoteURL": "",
"_clip": null,
"_playOnAwake": true,
"_volume": 1,
"_mute": false,
"_playbackRate": 1,
"_loop": true,
"_fullScreenOnAwake": false,
"_stayOnBottom": false,
"_keepAspectRatio": true,
"videoPlayerEvent": [],
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "a9HSqpEXNFpojuCAxNvLUJ"
},
{ {
"__type__": "cc.PrefabInfo", "__type__": "cc.PrefabInfo",
"root": { "root": {
@@ -570,7 +662,7 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 25 "__id__": 29
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
@@ -598,7 +690,7 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 27 "__id__": 31
}, },
"_alignFlags": 45, "_alignFlags": 45,
"_target": null, "_target": null,
@@ -634,7 +726,7 @@
}, },
"_enabled": true, "_enabled": true,
"__prefab": { "__prefab": {
"__id__": 29 "__id__": 33
}, },
"m_rootNode": null, "m_rootNode": null,
"image": { "image": {
@@ -643,8 +735,11 @@
"splash": { "splash": {
"__id__": 5 "__id__": 5
}, },
"videoArea": {
"__id__": 25
},
"videoPlayer": { "videoPlayer": {
"__id__": 21 "__id__": 22
}, },
"_id": "" "_id": ""
}, },