修改粒子命名规则
This commit is contained in:
1 parent
1ecbb6fc48
commit
aabf4ff693
10 files changed
+235
-97
No files matched your search
@@ -0,0 +1,107 @@
|
||||
import { build } from 'esbuild'
|
||||
|
||||
const source = `
|
||||
import { buildSpineJson } from './src/export/spineJsonExporter.ts'
|
||||
import { validateSpineJson } from './src/export/spineJsonValidator.ts'
|
||||
|
||||
const frameTexture = { width: 8, height: 8 }
|
||||
const single = {
|
||||
id: 1, imageMode: 'single', sequenceFrames: [], textureName: 'star.png', textureFolder: '',
|
||||
anchorX: 0.5, anchorY: 0.5, blend: 'normal', independentAlpha: 'off', texture: frameTexture,
|
||||
}
|
||||
const sequence = {
|
||||
id: 2, imageMode: 'sequence', sequenceFrames: [
|
||||
{ name: 'seq_0.png', previewUrl: '', texture: frameTexture },
|
||||
{ name: 'seq_1.png', previewUrl: '', texture: frameTexture },
|
||||
{ name: 'seq_2.png', previewUrl: '', texture: frameTexture },
|
||||
], textureName: 'seq.png', textureFolder: '',
|
||||
anchorX: 0.5, anchorY: 0.5, blend: 'add', independentAlpha: 'off', texture: frameTexture,
|
||||
}
|
||||
const trailState = (x) => ({
|
||||
bones: [0, 1, 2].map((index) => ({
|
||||
boneName: 'p_0_trail_' + index, x: x - index * 5, y: 0, rotation: 0,
|
||||
worldX: x - index * 5, worldY: 0, worldRotation: 0,
|
||||
})),
|
||||
width: 20, alpha: 1, colorHex: 0xffffff, resourceId: 1,
|
||||
})
|
||||
const particle = (boneName, spawnId, resourceId, imageFrameIndex, x, trail) => ({
|
||||
active: true, boneName, spawnId, resourceId, imageFrameIndex,
|
||||
imageVisible: true, colorHex: 0xffffff, alpha: 1,
|
||||
x, y: 0, rotation: 0, scaleX: 1, scaleY: 1,
|
||||
worldX: x, worldY: 0, worldRotation: 0, worldScaleX: 1, worldScaleY: 1,
|
||||
trailState: trail,
|
||||
})
|
||||
const frames = Array.from({ length: 6 }, (_, frame) => [
|
||||
particle('p_0', 1, 1, 0, frame, trailState(frame)),
|
||||
particle('p_1', 2, 2, frame % 3, frame * 2),
|
||||
])
|
||||
const system = {
|
||||
id: 1, animation: 'animation', visible: true, frames,
|
||||
config: {
|
||||
name: 'lizi_1', mode: 'burst', lifeMode: 'fixed', lifeMin: 1, lifeMax: 1, delay: 0,
|
||||
imageResources: [single, sequence], trail: true,
|
||||
trailResources: [{
|
||||
id: 1, texture: frameTexture, textureName: 'trail.png', blend: 'normal', boneCount: 3,
|
||||
lengthMode: 'fixed', length: 100, widthSizeMode: 'fixed', width: 100, widthMode: 'particle',
|
||||
}],
|
||||
},
|
||||
}
|
||||
const settings = {
|
||||
imagesPath: './images/', spineVersion: '4.2', keyframeCurve: 'linear', fps: 30,
|
||||
omitFps: false, integerFrameAlignment: true, bonePool: true,
|
||||
excludeEmptyAnimations: false, fileName: 'naming.json',
|
||||
}
|
||||
const result = buildSpineJson({ systems: [system], timeline: { fps: 30, animations: ['animation'] }, settings })
|
||||
validateSpineJson(result.text, '4.2')
|
||||
const json = JSON.parse(result.text)
|
||||
const failures = []
|
||||
const bone = (name) => json.bones.find((item) => item.name === name)
|
||||
const slot = (name) => json.slots.find((item) => item.name === name)
|
||||
|
||||
// 1. root 下的粒子根节点 = 系统名
|
||||
if (!bone('lizi_1') || bone('lizi_1').parent !== 'root') failures.push('粒子根节点应为 lizi_1 且父级为 root')
|
||||
// 2. 粒子骨骼 = 系统名_序号(父级为根节点)
|
||||
for (const name of ['lizi_1_0', 'lizi_1_1']) {
|
||||
if (!bone(name) || bone(name).parent !== 'lizi_1') failures.push('粒子骨骼命名/父级错误:' + name)
|
||||
}
|
||||
// 3. 插槽 = 系统名_序号_颜色模式(挂在对应骨骼下)
|
||||
if (!slot('lizi_1_0_normal') || slot('lizi_1_0_normal').bone !== 'lizi_1_0') failures.push('插槽应为 lizi_1_0_normal 且挂在 lizi_1_0')
|
||||
if (!slot('lizi_1_1_add') || slot('lizi_1_1_add').bone !== 'lizi_1_1') failures.push('插槽应为 lizi_1_1_add 且挂在 lizi_1_1')
|
||||
// 4. 图片附件:单图为系统名;序列帧加序号尾缀
|
||||
const skin = json.skins[0].attachments
|
||||
const singleAttachments = Object.keys(skin['lizi_1_0_normal'] || {})
|
||||
if (JSON.stringify(singleAttachments) !== JSON.stringify(['lizi_1'])) failures.push('单图附件应为 lizi_1,实际 ' + JSON.stringify(singleAttachments))
|
||||
const sequenceAttachments = Object.keys(skin['lizi_1_1_add'] || {}).sort()
|
||||
if (JSON.stringify(sequenceAttachments) !== JSON.stringify(['lizi_1_0', 'lizi_1_1', 'lizi_1_2'])) {
|
||||
failures.push('序列帧附件应为 lizi_1_0/1/2,实际 ' + JSON.stringify(sequenceAttachments))
|
||||
}
|
||||
// 动画里的附件时间轴要引用同样的名字
|
||||
const anim = json.animations.animation
|
||||
const usedNames = new Set((anim.slots['lizi_1_1_add']?.attachment || []).map((key) => key.name).filter(Boolean))
|
||||
for (const name of ['lizi_1_0', 'lizi_1_1', 'lizi_1_2']) if (!usedNames.has(name)) failures.push('序列帧动画未引用附件 ' + name)
|
||||
if (!(anim.slots['lizi_1_0_normal']?.attachment || []).some((key) => key.name === 'lizi_1')) failures.push('单图动画未引用附件 lizi_1')
|
||||
|
||||
// 拖尾骨骼同样遵循“系统名_序号”前缀,槽位挂在首个拖尾骨骼下。
|
||||
for (let index = 0; index < 3; index++) {
|
||||
const name = 'lizi_1_0_trail_1_' + index
|
||||
if (!bone(name) || bone(name).parent !== 'lizi_1') failures.push('拖尾骨骼命名/父级错误:' + name)
|
||||
}
|
||||
if (!slot('lizi_1_0_trail_1') || slot('lizi_1_0_trail_1').bone !== 'lizi_1_0_trail_1_0') {
|
||||
failures.push('拖尾插槽应为 lizi_1_0_trail_1 且挂在 lizi_1_0_trail_1_0')
|
||||
}
|
||||
|
||||
if (failures.length) { failures.forEach((message) => console.error('命名规则失败:' + message)); process.exitCode = 1 }
|
||||
else console.log('导出命名规则校验通过:lizi_1 / lizi_1_0 / lizi_1_0_normal / lizi_1(_序号)')
|
||||
`
|
||||
|
||||
const result = await build({
|
||||
stdin: { contents: source, resolveDir: process.cwd(), sourcefile: 'verify-spine-naming.ts', loader: 'ts' },
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
format: 'esm',
|
||||
write: false,
|
||||
logLevel: 'silent',
|
||||
})
|
||||
|
||||
const code = Buffer.from(result.outputFiles[0].contents).toString('base64')
|
||||
await import(`data:text/javascript;base64,${code}`)
|
||||
Reference in new issue
Block a user