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.
AdLike2048/assets/script/battle/skill/SkillTemplateScale.ts

75 lines
2.7 KiB

3 weeks ago
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,
);
}