You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
2.7 KiB
74 lines
2.7 KiB
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<Vec3>,
|
|
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,
|
|
);
|
|
}
|
|
|