feat(scripts): computeLpos / computeContentSize - 锚点转换公式(实测验证)
This commit is contained in:
+50
@@ -0,0 +1,50 @@
|
|||||||
|
import { test } from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { computeLpos, computeContentSize } from '../../scripts/legacy-layer-to-cocos-prefab.mjs';
|
||||||
|
|
||||||
|
test('computeLpos 锚点转换(实测验证:渠道logo)', () => {
|
||||||
|
const spirit = { x: '734', y: '143', w: '59', h: '148' };
|
||||||
|
const lpos = computeLpos(spirit);
|
||||||
|
// x = 734 + 59/2 - 640 = 123.5
|
||||||
|
// y = 360 - (143 + 148/2) = 143
|
||||||
|
assert.equal(lpos.x, 123.5);
|
||||||
|
assert.equal(lpos.y, 143);
|
||||||
|
assert.equal(lpos.z, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('computeLpos 锚点转换(实测验证:游客登录)', () => {
|
||||||
|
const spirit = { x: '540', y: '388', w: '320', h: '95' };
|
||||||
|
const lpos = computeLpos(spirit);
|
||||||
|
// x = 540 + 160 - 640 = 60
|
||||||
|
// y = 360 - (388 + 47.5) = -75.5
|
||||||
|
assert.equal(lpos.x, 60);
|
||||||
|
assert.equal(lpos.y, -75.5);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('computeLpos 字符串转数字(X/Y 为字符串 "0"/"-100")', () => {
|
||||||
|
const spirit = { x: '0', y: '-100', w: '100', h: '100' };
|
||||||
|
const lpos = computeLpos(spirit);
|
||||||
|
// x = 0 + 50 - 640 = -590
|
||||||
|
// y = 360 - (-100 + 50) = 410
|
||||||
|
assert.equal(lpos.x, -590);
|
||||||
|
assert.equal(lpos.y, 410);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('computeContentSize 直接读 Width/Height(SizeCalcMode=0 路径)', () => {
|
||||||
|
const spirit = { w: '320', h: '95', sizeCalcMode: '0' };
|
||||||
|
const size = computeContentSize(spirit);
|
||||||
|
assert.equal(size.width, 320);
|
||||||
|
assert.equal(size.height, 95);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('computeContentSize 默认 SizeCalcMode=0(字段缺失视作 0)', () => {
|
||||||
|
const spirit = { w: '100', h: '50' }; // no sizeCalcMode
|
||||||
|
const size = computeContentSize(spirit);
|
||||||
|
assert.equal(size.width, 100);
|
||||||
|
assert.equal(size.height, 50);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('computeContentSize SizeCalcMode=1 → throw(不静默)', () => {
|
||||||
|
const spirit = { w: '100', h: '50', sizeCalcMode: '1' };
|
||||||
|
assert.throws(() => computeContentSize(spirit), /SizeCalcMode=1.*reverse gameabc\.min\.js/);
|
||||||
|
});
|
||||||
@@ -53,3 +53,46 @@ export function readLayerXml(path) {
|
|||||||
|
|
||||||
return { layerId, layerName, spirits };
|
return { layerId, layerName, spirits };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 锚点转换: 原坐标系 (left-top, 1280×720 绝对) → Cocos 中心锚点 + Y-up.
|
||||||
|
*
|
||||||
|
* 公式 (实测验证 2026-09-02, Login_Layer 渠道logo + 游客登录双节点 _lpos 匹配):
|
||||||
|
* cocos_lpos.x = original_X + original_W/2 - 640 # 1280/2
|
||||||
|
* cocos_lpos.y = 360 - (original_Y + original_H/2) # Y-up 翻转 + 720/2
|
||||||
|
*
|
||||||
|
* @param {{ x?: string, y?: string, w?: string, h?: string }} spirit
|
||||||
|
* @returns {{ x: number, y: number, z: 0 }}
|
||||||
|
*/
|
||||||
|
export function computeLpos(spirit) {
|
||||||
|
const x = parseFloat(spirit.x || '0');
|
||||||
|
const y = parseFloat(spirit.y || '0');
|
||||||
|
const w = parseFloat(spirit.w || '0');
|
||||||
|
const h = parseFloat(spirit.h || '0');
|
||||||
|
// 锚点转换:原 X/Y 是左上角(1280×720 绝对坐标)→ Cocos 中心锚点
|
||||||
|
return {
|
||||||
|
x: x + w / 2 - 640, // 原坐标系半宽 1280/2
|
||||||
|
y: 360 - (y + h / 2), // Y-up 翻转 + 半高 720/2
|
||||||
|
z: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算 Spirit 的 contentSize (Cocos UI 节点尺寸).
|
||||||
|
*
|
||||||
|
* 数据源权威: SizeCalcMode 缺失视作 0 (直接读 Width/Height); 非 0 抛错,
|
||||||
|
* 由上游显式决定是否逆向 gameabc.min.js (Task 5 范围, 本任务不支持).
|
||||||
|
*
|
||||||
|
* @param {{ w?: string, h?: string, sizeCalcMode?: string, id?: string, name?: string }} spirit
|
||||||
|
* @returns {{ width: number, height: number }}
|
||||||
|
*/
|
||||||
|
export function computeContentSize(spirit) {
|
||||||
|
const sizeCalcMode = parseInt(spirit.sizeCalcMode || '0', 10);
|
||||||
|
if (sizeCalcMode !== 0) {
|
||||||
|
throw new Error(`SizeCalcMode=${sizeCalcMode} not yet supported for Spirit ${spirit.id} (${spirit.name}) - reverse gameabc.min.js first (Task 5)`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
width: parseFloat(spirit.w || '0'),
|
||||||
|
height: parseFloat(spirit.h || '0'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user