import { _decorator, Component, instantiate, Node, UITransform, Vec3, view, } from "cc"; import { DialogManager } from "../../manager/DialogManager"; import { DialogBubble } from "./DialogBubble"; import { Dialog } from "../../data/DialogData"; const { ccclass, property } = _decorator; @ccclass("ChatContentsLayout") export class ChatContentsLayout extends Component { manager: DialogManager = null; @property(Node) initPos: Node = null; @property(DialogBubble) lBubble: DialogBubble = null; @property(DialogBubble) rBubble: DialogBubble = null; bubbles: DialogBubble[] = []; cachedBubbles: DialogBubble[] = []; fixMaxWidth: number; protected start(): void { this.lBubble.node.active = false; this.rBubble.node.active = false; this.fixMaxWidth = view.getVisibleSize().width * 0.8; } protected onEnable(): void { if (!this.manager) this.manager = DialogManager.getInstance(); this.manager.layoutout = this; } UpdateDialog(dialogs: Dialog[]) { // 隐藏当前使用的气泡并放入缓存 for (let i = 0; i < this.bubbles.length; i++) { if (this.bubbles[i].node) { this.bubbles[i].node.active = false; this.cachedBubbles.push(this.bubbles[i]); } } this.bubbles = []; this.updateDialogLayout(dialogs); // 清理多余的缓存气泡,避免内存泄漏 this.cleanupExcessCachedBubbles(); } private updateDialogLayout(dialogs: Dialog[]) { let initPosY: number = this.initPos.position.y; let pendingUpdates = 0; const updateNextBubble = (index: number) => { if (index < 0) { return; } const dialog = dialogs[index]; let newBubble: DialogBubble = null; // 尝试从缓存中获取合适的气泡 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; 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); newBubble.init(); newBubbleNode.setParent(this.node); } newBubble.node.active = true; let pos = newBubble.node.position; newBubble.node.position = new Vec3(pos.x, initPosY, pos.z); pendingUpdates++; newBubble.updateBubbleContent(dialog.content, (actualHeight: number) => { initPosY += actualHeight + 20; pendingUpdates--; // 当当前气泡更新完成后,处理下一个 if (pendingUpdates === 0) { updateNextBubble(index - 1); } }, dialog.isLoading || false); this.bubbles.push(newBubble); }; // 从最后一个对话开始处理(倒序) 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(); } } } } }