/** One owner for home activity positions; visibility is still decided by each activity. */ export default class HomeActivityEntryLayout { private static signatures = new WeakMap(); private static leftNames = ["shop", "yicon", "redeemBtn", "passBtn", "jungle", "xinshou", "chengxu", "cloudRise"]; private static rightNames = ["rank", "gacha", "day", "hammer"]; static refresh(top: cc.Node): void { if (!top || !top.parent) return; const first = top.getChildByName("shop"), right = top.getChildByName("rank"); const footer = top.parent.getChildByName("shezhiBtn"); if (!first || !right || !footer) return; const left = this.leftNames.map(name => top.getChildByName(name)).filter(node => !!node); const fixedRight = this.rightNames.map(name => top.getChildByName(name)).filter(node => !!node); // Adaptation sets the same steady scale on Load and the side buttons. Ignore temporary button press zoom. const scale = Math.abs(top.parent.scaleY) || 1; const signature = JSON.stringify([first.x, first.y, right.x, top.y, scale, footer.y, footer.height, ...left.map(n => [n.name, n.active, n.width, n.height]), ...fixedRight.map(n => [n.name, n.active, n.x, n.y, n.width, n.height])]); if (this.signatures.get(top) === signature) return; this.signatures.set(top, signature); const footerTop = footer.y + footer.height * (1 - footer.anchorY) * scale - top.y + 16; let leftY = first.y + 220, leftBottom = Infinity; const occupiedRight = fixedRight.filter(n => n.active); let rightY = occupiedRight.length ? Math.min(...occupiedRight.map(n => n.y)) : first.y + 220; let rightBottom = occupiedRight.length ? Math.min(...occupiedRight.map(n => n.y + this.extent(n).bottom * scale)) : Infinity; for (const node of left.filter(n => n.active)) { const extent = this.extent(node), above = extent.top * scale, below = extent.bottom * scale; const y = Math.min(leftY - 220, leftBottom - 16 - above); if (y + below >= footerTop) { node.setPosition(first.x, y); leftY = y; leftBottom = y + below; } else { // Use the free lower right slots instead of covering the bottom-left Settings button. const nextY = Math.min(rightY - 220, rightBottom - 16 - above); node.setPosition(right.x, nextY); rightY = nextY; rightBottom = nextY + below; } } } /** Include clocks and labels below icons so the next entry cannot cover them. */ private static extent(node: cc.Node): { top: number; bottom: number } { let top = node.height * (1 - node.anchorY), bottom = -node.height * node.anchorY; for (const child of node.children) { if (!child.active) continue; const bounds = this.extent(child), scale = Math.abs(child.scaleY); top = Math.max(top, child.y + bounds.top * scale); bottom = Math.min(bottom, child.y + bounds.bottom * scale); } return { top, bottom }; } }