1.1.0版本
This commit is contained in:
1 parent
5cb2e76471
commit
deaefa6f8f
2 files changed
+233
-15
No files matched your search
+48
-9
@@ -15,6 +15,7 @@ const SKELETON_EXTS = ['.skel', '.skel.bytes', '.json'];
|
||||
const ATLAS_EXTS = ['.atlas', '.atlas.txt'];
|
||||
const TEXTURE_EXTS = ['.png', '.jpg', '.jpeg', '.webp'];
|
||||
const ALL_EXTS = SKELETON_EXTS.concat(ATLAS_EXTS, TEXTURE_EXTS);
|
||||
const fileIndexCache = new Map();
|
||||
|
||||
// Spine 导出常见的后缀,匹配时归一化掉
|
||||
const SUFFIX_RE = /-(pro|ess|pma|base|atlas|_pma|_pro|_ess)$/i;
|
||||
@@ -319,6 +320,22 @@ function collectSpineFiles(roots, validFolders) {
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 缩略图批量生成时,同一时刻会有很多 atlas/json/skel 回调。对全库文件清单做一个
|
||||
* 很短的缓存,下一轮轮询仍会重新扫描,因此既降低大文件夹导入开销,也不会漏掉
|
||||
* 正在落盘的新文件。
|
||||
*/
|
||||
function collectSpineFilesCached(filePath, roots) {
|
||||
const libRoot = findLibraryRoot(filePath);
|
||||
const key = libRoot || path.dirname(path.dirname(filePath));
|
||||
const now = Date.now();
|
||||
const cached = fileIndexCache.get(key);
|
||||
if (cached && now - cached.time < 180) return cached.files;
|
||||
const files = collectSpineFiles(roots, null);
|
||||
fileIndexCache.set(key, { time: now, files });
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修正不可靠的源路径。
|
||||
* Eagle 传给缩略图 handler 的 src 有时指向一个已清理/不存在的 `.info` 目录
|
||||
@@ -362,6 +379,7 @@ function discoverAssets(filePath, options) {
|
||||
options = options || {};
|
||||
const strictStem = !!options.strictStem;
|
||||
const preferCompatibleJson = !!options.preferCompatibleJson;
|
||||
const allowCrossBatch = !!options.allowCrossBatch;
|
||||
filePath = resolveRealSource(filePath);
|
||||
const selected = path.basename(filePath);
|
||||
const selectedStem = normalizeStem(selected);
|
||||
@@ -375,7 +393,14 @@ function discoverAssets(filePath, options) {
|
||||
// folders 的同批资源也纳入候选,之后用 metadata.json 的 birthtime 精确配对。
|
||||
const validFolders = getValidFolders(filePath);
|
||||
let files = collectSpineFiles(roots, validFolders);
|
||||
if (strictStem) files = collectSpineFiles(roots, null);
|
||||
if (strictStem) {
|
||||
const allFiles = collectSpineFilesCached(filePath, roots);
|
||||
if (allowCrossBatch && validFolders && validFolders.size) {
|
||||
files = allFiles.filter((f) => foldersOfItem(f.fullPath).some((id) => validFolders.has(id)));
|
||||
} else {
|
||||
files = allFiles;
|
||||
}
|
||||
}
|
||||
|
||||
const skeletonFiles = files.filter((f) => isSkeletonFile(f.name));
|
||||
const atlasFiles = files.filter((f) => isAtlasFile(f.name));
|
||||
@@ -403,11 +428,9 @@ function discoverAssets(filePath, options) {
|
||||
btimeDelta: refBtime ? Math.abs(btimeOf(c.fullPath) - refBtime) : Number.MAX_SAFE_INTEGER,
|
||||
};
|
||||
});
|
||||
ranked.sort((a, b) =>
|
||||
a.importDelta - b.importDelta ||
|
||||
b.sameFolder - a.sameFolder ||
|
||||
a.btimeDelta - b.btimeDelta ||
|
||||
a.c.fullPath.localeCompare(b.c.fullPath)
|
||||
ranked.sort((a, b) => allowCrossBatch
|
||||
? (b.sameFolder - a.sameFolder || a.importDelta - b.importDelta || a.btimeDelta - b.btimeDelta || a.c.fullPath.localeCompare(b.c.fullPath))
|
||||
: (a.importDelta - b.importDelta || b.sameFolder - a.sameFolder || a.btimeDelta - b.btimeDelta || a.c.fullPath.localeCompare(b.c.fullPath))
|
||||
);
|
||||
return ranked[0].c;
|
||||
};
|
||||
@@ -463,7 +486,7 @@ function discoverAssets(filePath, options) {
|
||||
f.name.toLowerCase().endsWith('.json') &&
|
||||
normalizeStem(f.name) === stem &&
|
||||
familyOfSkel(f) === familyOfSkel(skeleton) &&
|
||||
(!strictStem || Math.abs(importTimeOf(f.fullPath) - importTimeOf(skeleton.fullPath)) <= 30000)
|
||||
(!strictStem || allowCrossBatch || Math.abs(importTimeOf(f.fullPath) - importTimeOf(skeleton.fullPath)) <= 30000)
|
||||
);
|
||||
const jsonFallback = selectBest(jsonCands, skeleton.fullPath);
|
||||
if (jsonFallback) skeleton = jsonFallback;
|
||||
@@ -509,7 +532,7 @@ function discoverAssets(filePath, options) {
|
||||
|
||||
// 严格模式用于导入缩略图:配套骨骼和图集应由同一次拖入创建。若时间差
|
||||
// 过大,说明新同伴还没落盘,返回缺失让调用方继续等待,不能借用旧同名资源。
|
||||
if (strictStem && skeleton && atlas) {
|
||||
if (strictStem && !allowCrossBatch && skeleton && atlas) {
|
||||
const pairDelta = Math.abs(importTimeOf(skeleton.fullPath) - importTimeOf(atlas.fullPath));
|
||||
if (pairDelta > 30000) {
|
||||
if (isAtlasFile(selected)) skeleton = null;
|
||||
@@ -535,7 +558,7 @@ function discoverAssets(filePath, options) {
|
||||
let cands = textureFiles.filter((f) => f.name.toLowerCase() === pn.toLowerCase());
|
||||
if (cands.length === 0) cands = textureFiles.filter((f) => normalizeStem(f.name) === normalizeStem(pn));
|
||||
let hit = selectBest(cands, atlas.fullPath);
|
||||
if (strictStem && hit && Math.abs(importTimeOf(hit.fullPath) - importTimeOf(atlas.fullPath)) > 30000) hit = null;
|
||||
if (strictStem && !allowCrossBatch && hit && Math.abs(importTimeOf(hit.fullPath) - importTimeOf(atlas.fullPath)) > 30000) hit = null;
|
||||
if (hit) texturePaths[pn] = hit.fullPath;
|
||||
}
|
||||
}
|
||||
@@ -543,6 +566,21 @@ function discoverAssets(filePath, options) {
|
||||
const base = skeleton ? normalizeStem(skeleton.name) : (atlas ? normalizeStem(atlas.name) : selectedStem);
|
||||
const skelLower = skeleton ? skeleton.name.toLowerCase() : '';
|
||||
const skeletonIsBinary = skelLower.endsWith('.skel') || skelLower.endsWith('.skel.bytes');
|
||||
const chosenFamily = skeleton ? familyOfSkel(skeleton) : (atlas ? familyOfAtlas(atlas) : null);
|
||||
const skeletonTime = skeleton ? importTimeOf(skeleton.fullPath) : 0;
|
||||
const atlasTime = atlas ? importTimeOf(atlas.fullPath) : 0;
|
||||
const relatedSkeletonPaths = skeleton ? realSkeletonFiles.filter((f) =>
|
||||
normalizeStem(f.name) === base &&
|
||||
familyOfSkel(f) === chosenFamily &&
|
||||
Math.abs(importTimeOf(f.fullPath) - skeletonTime) <= 30000
|
||||
).map((f) => f.fullPath) : [];
|
||||
const relatedAtlasPaths = atlas ? atlasFiles.filter((f) =>
|
||||
normalizeStem(f.name) === base &&
|
||||
familyOfAtlas(f) === chosenFamily &&
|
||||
Math.abs(importTimeOf(f.fullPath) - atlasTime) <= 30000
|
||||
).map((f) => f.fullPath) : [];
|
||||
const relatedDataPaths = [...new Set(relatedSkeletonPaths.concat(relatedAtlasPaths, [filePath]))]
|
||||
.filter((fp) => isSkeletonFile(fp) || isAtlasFile(fp));
|
||||
|
||||
return {
|
||||
skeletonPath: skeleton ? skeleton.fullPath : null,
|
||||
@@ -555,6 +593,7 @@ function discoverAssets(filePath, options) {
|
||||
atlasCandidates: atlasFiles.map((f) => f.name),
|
||||
atlasCandidatePaths: atlasFiles.map((f) => f.fullPath),
|
||||
textureCandidates: textureFiles.map((f) => f.name),
|
||||
relatedDataPaths,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user