导出修正

This commit is contained in:
tianmo committed 2026-09-12 12:17:26 +08:00
1 parent ee72d09b23
commit 6de6e2cf5b
7 files changed
+1260 -1248

No files matched your search

+16 -4
View File
@@ -71,6 +71,15 @@ function collectTracks(frames: ParticleState[][], bonePool: boolean, usedNames:
}))
}
/**
* 轨道在时间轴上真正使用到的图片资源(骨骼池模式下同一轨道先后出生多颗粒子,可能用到多张)。
* 只有用到的图片才会挂到该轨道的插槽下,避免没用到的附件也占位。
*/
function trackImageResources(system: ParticleSystem, track: Track) {
const usedIds = new Set(track.states.map((state) => state?.resourceId).filter((id): id is number => typeof id === 'number'))
return system.config.imageResources.filter((resource) => usedIds.has(resource.id))
}
function sourceStateAt(track: Track, targetFrame: number, sourceFps: number, targetFps: number) {
const source = targetFrame * sourceFps / targetFps
const aIndex = Math.min(track.states.length - 1, Math.max(0, Math.floor(source)))
@@ -273,12 +282,14 @@ export function buildSpineJson(input: ExportInput): SpineExportResult {
for (const track of tracks) {
document.bones.push({ name: track.name, parent: prefix })
const usedImageBlends = new Set(system.config.imageResources.map((item) => item.blend))
const imageResources = trackImageResources(system, track)
const usedImageBlends = new Set(imageResources.map((item) => item.blend))
for (const blend of usedImageBlends) {
const slotName = `${track.name}_image_${blend}`
document.slots.push({ name: slotName, bone: track.name, color: 'ffffff00', blend: BLENDS[blend] })
const slotSkin = skin[slotName] ||= {}
for (const resource of system.config.imageResources.filter((item) => item.blend === blend)) {
// 只挂该轨道真正用到的图片;序列帧资源包含全部帧(每帧都会被播放到)。
for (const resource of imageResources.filter((item) => item.blend === blend)) {
const count = resource.imageMode === 'sequence' ? Math.max(1, resource.sequenceFrames.length) : 1
for (let frame = 0; frame < count; frame++) slotSkin[`image_${resource.id}_${frame}`] = resourceAttachment(resource, frame, warnings)
}
@@ -342,7 +353,8 @@ export function buildSpineJson(input: ExportInput): SpineExportResult {
if (scale.length) boneTimeline.scale = scale
if (Object.keys(boneTimeline).length) { animation.bones[track.name] = boneTimeline; hasContent = true }
const usedBlends = new Set(system.config.imageResources.map((item) => item.blend))
const imageResources = trackImageResources(system, track)
const usedBlends = new Set(imageResources.map((item) => item.blend))
for (const blend of usedBlends) {
const attachments: Array<string | null> = [], colors: number[][] = []
let lastColor = 0xffffff
@@ -354,7 +366,7 @@ export function buildSpineJson(input: ExportInput): SpineExportResult {
attachments.push(visible ? `image_${resource!.id}_${state!.imageFrameIndex ?? 0}` : null)
colors.push(rgbaValues(lastColor, visible ? state!.alpha : 0))
}
const blendResources = system.config.imageResources.filter((item) => item.blend === blend)
const blendResources = imageResources.filter((item) => item.blend === blend)
const requestedModes = blendResources
.filter((item) => item.independentAlpha === 'curve')
.map((item) => resolvedTimelineCurve(item.alphaCurveMode, settings))