Files
18xchat/assets/Scripts/chat18x/ui/components/ChatContentsLayout.ts
T

135 lines
3.7 KiB
TypeScript
Raw Normal View History

2025-08-15 18:17:12 +08:00
import {
_decorator,
Component,
instantiate,
Node,
UITransform,
Vec3,
2025-08-27 16:12:19 +08:00
view,
2025-08-15 18:17:12 +08:00
} from "cc";
2025-08-11 16:08:59 +08:00
import { DialogManager } from "../../manager/DialogManager";
2025-07-21 22:14:06 +08:00
import { DialogBubble } from "./DialogBubble";
import { Dialog } from "../../data/DialogData";
2025-07-21 22:14:06 +08:00
const { ccclass, property } = _decorator;
@ccclass("ChatContentsLayout")
export class ChatContentsLayout extends Component {
2025-08-11 16:08:59 +08:00
manager: DialogManager = null;
2025-07-21 22:14:06 +08:00
2025-08-15 18:17:12 +08:00
@property(Node)
initPos: Node = null;
2025-07-21 22:14:06 +08:00
@property(DialogBubble)
lBubble: DialogBubble = null;
@property(DialogBubble)
rBubble: DialogBubble = null;
bubbles: DialogBubble[] = [];
cachedBubbles: DialogBubble[] = [];
2025-07-21 22:14:06 +08:00
2025-08-15 18:17:12 +08:00
fixMaxWidth: number;
2025-07-21 22:14:06 +08:00
protected start(): void {
this.lBubble.node.active = false;
this.rBubble.node.active = false;
2025-08-27 16:12:19 +08:00
this.fixMaxWidth = view.getVisibleSize().width * 0.8;
2025-07-22 16:43:10 +08:00
}
protected onEnable(): void {
2025-08-11 16:08:59 +08:00
if (!this.manager) this.manager = DialogManager.getInstance();
2025-07-22 16:43:10 +08:00
2025-07-21 22:14:06 +08:00
this.manager.layoutout = this;
}
UpdateDialog(dialogs: Dialog[]) {
// 隐藏当前使用的气泡并放入缓存
for (let i = 0; i < this.bubbles.length; i++) {
2025-07-21 22:14:06 +08:00
if (this.bubbles[i].node) {
this.bubbles[i].node.active = false;
this.cachedBubbles.push(this.bubbles[i]);
2025-07-21 22:14:06 +08:00
}
}
this.bubbles = [];
2025-08-15 18:17:12 +08:00
2025-08-13 12:55:27 +08:00
this.updateDialogLayout(dialogs);
2025-08-15 18:17:12 +08:00
2025-08-13 12:55:27 +08:00
// 清理多余的缓存气泡,避免内存泄漏
this.cleanupExcessCachedBubbles();
}
private updateDialogLayout(dialogs: Dialog[]) {
2025-08-15 18:17:12 +08:00
let initPosY: number = this.initPos.position.y;
2025-08-13 12:55:27 +08:00
let pendingUpdates = 0;
2025-08-15 18:17:12 +08:00
2025-08-13 12:55:27 +08:00
const updateNextBubble = (index: number) => {
if (index < 0) {
return;
}
2025-08-15 18:17:12 +08:00
2025-08-13 12:55:27 +08:00
const dialog = dialogs[index];
let newBubble: DialogBubble = null;
2025-07-21 22:14:06 +08:00
// 尝试从缓存中获取合适的气泡
const isPlayerBubble = dialog.isPlayer;
for (let j = 0; j < this.cachedBubbles.length; j++) {
const cached = this.cachedBubbles[j];
if (cached && cached.node) {
// 检查气泡类型是否匹配(通过位置判断左右气泡)
const isRightBubble = cached.node.position.x > 0;
2025-08-15 18:17:12 +08:00
if (
(isPlayerBubble && isRightBubble) ||
(!isPlayerBubble && !isRightBubble)
) {
newBubble = cached;
this.cachedBubbles.splice(j, 1);
break;
}
}
}
// 如果缓存中没有合适的气泡,创建新的
if (!newBubble) {
let newBubbleNode = isPlayerBubble
? instantiate(this.rBubble.node)
: instantiate(this.lBubble.node);
newBubble = newBubbleNode.getComponent(DialogBubble);
2025-08-27 16:12:19 +08:00
newBubble.init();
newBubbleNode.setParent(this.node);
}
2025-07-21 22:14:06 +08:00
newBubble.node.active = true;
let pos = newBubble.node.position;
newBubble.node.position = new Vec3(pos.x, initPosY, pos.z);
2025-08-15 18:17:12 +08:00
2025-08-13 12:55:27 +08:00
pendingUpdates++;
newBubble.updateBubbleContent(dialog.content, (actualHeight: number) => {
initPosY += actualHeight + 20;
pendingUpdates--;
2025-08-15 18:17:12 +08:00
2025-08-13 12:55:27 +08:00
// 当当前气泡更新完成后,处理下一个
if (pendingUpdates === 0) {
updateNextBubble(index - 1);
}
2025-08-27 16:12:19 +08:00
}, dialog.isLoading || false);
2025-08-15 18:17:12 +08:00
2025-07-21 22:14:06 +08:00
this.bubbles.push(newBubble);
2025-08-13 12:55:27 +08:00
};
2025-08-15 18:17:12 +08:00
2025-08-13 12:55:27 +08:00
// 从最后一个对话开始处理(倒序)
updateNextBubble(dialogs.length - 1);
}
private cleanupExcessCachedBubbles() {
const maxCachedBubbles = 20; // 最大缓存数量
if (this.cachedBubbles.length > maxCachedBubbles) {
const excessCount = this.cachedBubbles.length - maxCachedBubbles;
for (let i = 0; i < excessCount; i++) {
const bubble = this.cachedBubbles.shift();
if (bubble && bubble.node) {
bubble.node.destroy();
}
}
}
2025-07-21 22:14:06 +08:00
}
}