import { Node, UITransform, Vec3 } from 'cc'; /** * 技能表现缩放:预制体 UITransform = scale 1 时美术基准; * 基准世界半径 = 半宽 × 父链 worldScale;配表半径只参与比值,不写回预制体。 */ /** 模板在预制体层级下短暂激活后采样的世界半径(半宽 × |worldScale|) */ export function measureTemplateWorldRadius(template: Node | null): number | null { if (!template?.isValid) return null; const ut = template.getComponent(UITransform); const w = ut?.contentSize.width ?? 0; if (!(w > 0)) return null; const wasActive = template.active; template.active = true; const ws = Math.max(Math.abs(template.worldScale.x), Math.abs(template.worldScale.y), 1e-6); template.active = wasActive; return (w * 0.5) * ws; } /** 已挂到场景中的节点世界半径 */ export function measureNodeWorldRadius(node: Node | null): number | null { if (!node?.isValid) return null; const ut = node.getComponent(UITransform); const w = ut?.contentSize.width ?? 0; if (!(w > 0)) return null; const ws = Math.max(Math.abs(node.worldScale.x), Math.abs(node.worldScale.y), 1e-6); return (w * 0.5) * ws; } /** * 克隆/实例挂到 host 后,按配表世界半径设置绝对 worldScale。 * template 用于测量设计基准(含原父链缩放)。 */ export function applyConfigWorldRadius( node: Node, template: Node, configRadiusPx: number, ): boolean { const artWorldRadius = measureTemplateWorldRadius(template); if (artWorldRadius == null || !(artWorldRadius > 0) || !(configRadiusPx > 0)) return false; const ratio = configRadiusPx / artWorldRadius; const wasActive = template.active; template.active = true; const tplWs = template.worldScale; template.active = wasActive; const baseMag = Math.max(Math.abs(tplWs.x), Math.abs(tplWs.y), 1e-6); const targetMag = Math.max(0.2, baseMag * ratio); node.setScale(1, 1, 1); node.setWorldScale( tplWs.x >= 0 ? targetMag : -targetMag, tplWs.y >= 0 ? targetMag : -targetMag, 1, ); return true; } /** * 节点仍挂在模板原父级下时,用 localScale 达到配表世界半径(如音波留在 anim 下)。 */ export function computeLocalScaleForConfigRadius( template: Node, initLocalScale: Readonly, configRadiusPx: number, ): Vec3 | null { const artWorldRadius = measureTemplateWorldRadius(template); if (artWorldRadius == null || !(artWorldRadius > 0) || !(configRadiusPx > 0)) return null; const ratio = Math.max(0.2, configRadiusPx / artWorldRadius); return new Vec3( initLocalScale.x * ratio, initLocalScale.y * ratio, initLocalScale.z, ); }