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.
86 lines
3.0 KiB
86 lines
3.0 KiB
import type { RefRecord, StaticAssetKind } from '../shared/types.js';
|
|
import { membershipDedupeArray } from '../shared/MembershipSet.js';
|
|
import { fileNameFromUrl } from './asset-tree.js';
|
|
import { getAssetKind, readJsonFile } from './file-util.js';
|
|
import { extractFlatJsonRefs, extractSceneRefs } from './scene-parser.js';
|
|
|
|
interface ScanMeta {
|
|
uuid: string;
|
|
url: string;
|
|
file: string;
|
|
kind: StaticAssetKind;
|
|
}
|
|
|
|
export async function scanAssetFile(fsPath: string): Promise<RefRecord[]> {
|
|
const url = await Editor.Message.request('asset-db', 'query-url', fsPath);
|
|
if (!url || String(url).includes('db://internal')) {
|
|
return [];
|
|
}
|
|
const uuid = await Editor.Message.request('asset-db', 'query-uuid', url);
|
|
if (!uuid) {
|
|
return [];
|
|
}
|
|
const kind = getAssetKind(fsPath);
|
|
if (!kind) {
|
|
return [];
|
|
}
|
|
const data = await readJsonFile(fsPath);
|
|
if (!data) {
|
|
return [];
|
|
}
|
|
const meta: ScanMeta = { uuid, url: String(url).split('@')[0], file: fsPath, kind };
|
|
if (kind === 'prefab' || kind === 'scene') {
|
|
return extractSceneRefs(data as never[], meta);
|
|
}
|
|
return extractFlatJsonRefs(data, meta);
|
|
}
|
|
|
|
/** 填充 targetUrl/targetName(批量,减少 asset-db 调用) */
|
|
export async function hydrateRefRecords(records: RefRecord[]): Promise<void> {
|
|
const uuids = membershipDedupeArray(records.map((r) => r.targetUuid));
|
|
const infoMap = new Map<string, { url: string; name: string }>();
|
|
for (const uuid of uuids) {
|
|
try {
|
|
const info = await Editor.Message.request('asset-db', 'query-asset-info', uuid);
|
|
if (info?.url) {
|
|
const mainUrl = String(info.url).split('@')[0];
|
|
infoMap.set(uuid, { url: mainUrl, name: fileNameFromUrl(mainUrl) });
|
|
}
|
|
} catch {
|
|
// ignore missing assets
|
|
}
|
|
}
|
|
for (const record of records) {
|
|
const info = infoMap.get(record.targetUuid);
|
|
if (info) {
|
|
record.targetUrl = info.url;
|
|
record.targetName = info.name;
|
|
} else {
|
|
record.targetUrl = '';
|
|
record.targetName = record.targetUuid.slice(0, 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function hydrateSourceNames(records: RefRecord[]): Promise<void> {
|
|
const uuids = membershipDedupeArray(records.map((r) => r.sourceUuid));
|
|
const infoMap = new Map<string, { url: string; name: string }>();
|
|
for (const uuid of uuids) {
|
|
try {
|
|
const info = await Editor.Message.request('asset-db', 'query-asset-info', uuid);
|
|
if (info?.url) {
|
|
const mainUrl = String(info.url).split('@')[0];
|
|
infoMap.set(uuid, { url: mainUrl, name: fileNameFromUrl(mainUrl) });
|
|
}
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
for (const record of records) {
|
|
const info = infoMap.get(record.sourceUuid);
|
|
if (info) {
|
|
record.sourceUrl = info.url;
|
|
record.sourceName = info.name;
|
|
}
|
|
}
|
|
}
|
|
|