fix(POSTV1-TEMPLATE-FIDELITY-17): 修复模板图案还原与预览状态
Dada P0-A isolated Windows CI / validate-and-package (push) Waiting to run
Dada P0-A isolated Windows CI / validate-and-package (push) Waiting to run
This commit is contained in:
@@ -280,6 +280,7 @@ function manifestFileMap(packageFiles) {
|
||||
filesByAsciiIdentity.set(asciiIdentity, asciiValues);
|
||||
}
|
||||
const mappings = new Map();
|
||||
const spriteDefinitions = new Map();
|
||||
const manifestEntries = [];
|
||||
for (const path of packageFiles.filter((candidate) => extname(candidate).toLowerCase() === ".manifest")) {
|
||||
let manifest;
|
||||
@@ -299,7 +300,10 @@ function manifestFileMap(packageFiles) {
|
||||
const resolved = existsSync(candidate) ? candidate
|
||||
: filesByName.get(normalizedName)?.[0]
|
||||
?? (asciiCandidates.length === 1 ? asciiCandidates[0] : undefined);
|
||||
if (resolved) mappings.set(uuid, resolved);
|
||||
if (resolved) {
|
||||
mappings.set(uuid, resolved);
|
||||
if (assetFileType(resolved) === "sprite") spriteDefinitions.set(uuid, resolved);
|
||||
}
|
||||
else mappings.set(uuid, fileName);
|
||||
}
|
||||
}
|
||||
@@ -333,9 +337,13 @@ function manifestFileMap(packageFiles) {
|
||||
const imagePath = imageEntry ? actualImagesByUuid.get(imageEntry.uuid) ?? mappings.get(imageEntry.uuid)
|
||||
: inferredImageUuid ? actualImagesByUuid.get(inferredImageUuid) ?? mappings.get(inferredImageUuid)
|
||||
: undefined;
|
||||
const spriteDefinition = matchingActualSprites.length === 1 ? matchingActualSprites[0].path : mappings.get(spriteEntry.uuid);
|
||||
if (typeof spriteDefinition === "string" && existsSync(spriteDefinition) && assetFileType(spriteDefinition) === "sprite") {
|
||||
spriteDefinitions.set(spriteEntry.uuid, spriteDefinition);
|
||||
}
|
||||
if (typeof imagePath === "string" && existsSync(imagePath)) mappings.set(spriteEntry.uuid, imagePath);
|
||||
}
|
||||
return mappings;
|
||||
return { mappings, spriteDefinitions };
|
||||
}
|
||||
|
||||
function colorHex(value, fallback = "#111111") {
|
||||
@@ -350,6 +358,29 @@ function quaternionDegrees(rotation) {
|
||||
return Math.atan2(2 * w * z, 1 - 2 * z * z) * 180 / Math.PI;
|
||||
}
|
||||
|
||||
function spriteNinePatch(sprite) {
|
||||
const object = sprite?.object;
|
||||
if (Number(object?.m_type) !== 3) return undefined;
|
||||
const sourceWidth = Number(object.m_width);
|
||||
const sourceHeight = Number(object.m_height);
|
||||
const left = Number(object.m_startW);
|
||||
const rightEdge = Number(object.m_endW);
|
||||
const top = Number(object.m_startH);
|
||||
const bottomEdge = Number(object.m_endH);
|
||||
if (![sourceWidth, sourceHeight, left, rightEdge, top, bottomEdge].every(Number.isFinite)
|
||||
|| sourceWidth <= 0 || sourceHeight <= 0
|
||||
|| left < 0 || rightEdge < left || rightEdge > sourceWidth
|
||||
|| top < 0 || bottomEdge < top || bottomEdge > sourceHeight) return undefined;
|
||||
return {
|
||||
bottom: sourceHeight - bottomEdge,
|
||||
left,
|
||||
right: sourceWidth - rightEdge,
|
||||
source_height: sourceHeight,
|
||||
source_width: sourceWidth,
|
||||
top,
|
||||
};
|
||||
}
|
||||
|
||||
function pngDimensions(path) {
|
||||
const bytes = readFileSync(path);
|
||||
if (bytes.length < 24 || bytes.readUInt32BE(12) !== 0x49484452) return undefined;
|
||||
@@ -437,12 +468,18 @@ function prefabLayers(prefab, input) {
|
||||
const localScale = local.m_Scale ?? {};
|
||||
const scaleX = parent.scaleX * Number(localScale.x ?? 1);
|
||||
const scaleY = parent.scaleY * Number(localScale.y ?? 1);
|
||||
const localX = ignorePosition ? 0 : Number(localPosition.x ?? 0) * parent.scaleX;
|
||||
const localY = ignorePosition ? 0 : Number(localPosition.y ?? 0) * parent.scaleY;
|
||||
const parentRadians = parent.rotation * Math.PI / 180;
|
||||
const transform = {
|
||||
alpha: parent.alpha * Math.max(0, Math.min(1, Number(object.m_CustomAlpha ?? 1))),
|
||||
anchorX: Math.max(0, Math.min(1, Number(object.m_anchorPoint?.x ?? 0.5))),
|
||||
anchorY: Math.max(0, Math.min(1, Number(object.m_anchorPoint?.y ?? 0.5))),
|
||||
rotation: parent.rotation + quaternionDegrees(local.m_Rotation),
|
||||
scaleX,
|
||||
scaleY,
|
||||
x: parent.x + (ignorePosition ? 0 : Number(localPosition.x ?? 0) * parent.scaleX),
|
||||
y: parent.y + (ignorePosition ? 0 : Number(localPosition.y ?? 0) * parent.scaleY),
|
||||
x: parent.x + localX * Math.cos(parentRadians) - localY * Math.sin(parentRadians),
|
||||
y: parent.y + localX * Math.sin(parentRadians) + localY * Math.cos(parentRadians),
|
||||
};
|
||||
const nodeComponents = components(object, resolve);
|
||||
const localUnderlines = [
|
||||
@@ -460,6 +497,9 @@ function prefabLayers(prefab, input) {
|
||||
const fontUuid = textMesh.m_font?.uuid?.uuid;
|
||||
layers.push({
|
||||
align: Number(style.alignment ?? 0) === 2 ? "right" : Number(style.alignment ?? 0) === 1 ? "left" : "center",
|
||||
...(transform.alpha === 1 ? {} : { alpha: transform.alpha }),
|
||||
...(transform.anchorX === 0.5 ? {} : { anchor_x: transform.anchorX }),
|
||||
...(transform.anchorY === 0.5 ? {} : { anchor_y: transform.anchorY }),
|
||||
fill_color: colorHex(style.color),
|
||||
fill_pattern_asset_id: firstMaterialTextureAssetId(textRenderer, input),
|
||||
font_file: typeof fontUuid === "string" ? input.manifestMappings.get(fontUuid) : undefined,
|
||||
@@ -496,6 +536,7 @@ function prefabLayers(prefab, input) {
|
||||
const naturalRatio = dimensions ? dimensions.height / Math.max(1, dimensions.width) : 0.15;
|
||||
const targetHeight = Math.max(2, Math.min(Number(object.m_contentSize?.height ?? 48) * 0.65, targetWidth * naturalRatio));
|
||||
layers.push({
|
||||
...(transform.alpha === 1 ? {} : { alpha: transform.alpha }),
|
||||
asset_id: assetId,
|
||||
height: targetHeight,
|
||||
order: order++,
|
||||
@@ -516,7 +557,9 @@ function prefabLayers(prefab, input) {
|
||||
const assetId = typeof texturePath === "string" ? input.imageIds.get(texturePath) : undefined;
|
||||
if (!assetId) continue;
|
||||
layers.push({
|
||||
alpha: Math.max(0, Math.min(1, Number(particleComponent.m_AlphaIdensity ?? 1))),
|
||||
alpha: transform.alpha * Math.max(0, Math.min(1, Number(particleComponent.m_AlphaIdensity ?? 1))),
|
||||
anchor_x: transform.anchorX,
|
||||
anchor_y: transform.anchorY,
|
||||
asset_id: assetId,
|
||||
atlas_columns: Math.max(1, Number(particleComponent.m_altasUcount ?? 1)),
|
||||
atlas_rows: Math.max(1, Number(particleComponent.m_altasVcount ?? 1)),
|
||||
@@ -542,15 +585,28 @@ function prefabLayers(prefab, input) {
|
||||
if (spriteRenderer && spriteRenderer.m_isEnabled !== false) {
|
||||
const spriteUuid = spriteRenderer?.m_sprite?.uuid?.uuid;
|
||||
const spritePath = typeof spriteUuid === "string" ? input.manifestMappings.get(spriteUuid) : undefined;
|
||||
const spriteDefinitionPath = typeof spriteUuid === "string" ? input.spriteDefinitions.get(spriteUuid) : undefined;
|
||||
let imagePath;
|
||||
if (typeof spritePath === "string" && assetFileType(spritePath) === "sprite" && existsSync(spritePath)) {
|
||||
let ninePatch;
|
||||
if (typeof spriteDefinitionPath === "string" && existsSync(spriteDefinitionPath)) {
|
||||
const sprite = readJson(spriteDefinitionPath);
|
||||
const imageUuid = sprite?.object?.m_UUIDList?.[0]?.uuid;
|
||||
imagePath = typeof spritePath === "string" && assetFileType(spritePath) === "png"
|
||||
? spritePath
|
||||
: typeof imageUuid === "string" ? input.manifestMappings.get(imageUuid) : undefined;
|
||||
ninePatch = spriteNinePatch(sprite);
|
||||
} else if (typeof spritePath === "string" && assetFileType(spritePath) === "sprite" && existsSync(spritePath)) {
|
||||
const sprite = readJson(spritePath);
|
||||
const imageUuid = sprite?.object?.m_UUIDList?.[0]?.uuid;
|
||||
if (typeof imageUuid === "string") imagePath = input.manifestMappings.get(imageUuid);
|
||||
ninePatch = spriteNinePatch(sprite);
|
||||
} else if (typeof spritePath === "string" && assetFileType(spritePath) === "png") imagePath = spritePath;
|
||||
const assetId = typeof imagePath === "string" ? input.imageIds.get(imagePath) : undefined;
|
||||
if (assetId) {
|
||||
layers.push({
|
||||
...(transform.alpha === 1 ? {} : { alpha: transform.alpha }),
|
||||
...(transform.anchorX === 0.5 ? {} : { anchor_x: transform.anchorX }),
|
||||
...(transform.anchorY === 0.5 ? {} : { anchor_y: transform.anchorY }),
|
||||
asset_id: assetId,
|
||||
height: Math.max(1, Number(object.m_contentSize?.height ?? 1) * Math.abs(scaleY)),
|
||||
order: order++,
|
||||
@@ -561,6 +617,7 @@ function prefabLayers(prefab, input) {
|
||||
width: Math.max(1, Number(object.m_contentSize?.width ?? 1) * Math.abs(scaleX)),
|
||||
x: transform.x,
|
||||
y: transform.y,
|
||||
...(ninePatch ? { nine_patch: ninePatch } : {}),
|
||||
});
|
||||
} else {
|
||||
input.unresolvedImages.push({ spriteUuid, spritePath });
|
||||
@@ -568,7 +625,7 @@ function prefabLayers(prefab, input) {
|
||||
}
|
||||
for (const child of object.m_Children ?? []) visit(child, transform);
|
||||
};
|
||||
for (const child of root?.m_Children ?? []) visit(child, { rotation: 0, scaleX: 1, scaleY: 1, x: 0, y: 0 }, true);
|
||||
for (const child of root?.m_Children ?? []) visit(child, { alpha: 1, rotation: 0, scaleX: 1, scaleY: 1, x: 0, y: 0 }, true);
|
||||
return layers;
|
||||
}
|
||||
|
||||
@@ -593,12 +650,28 @@ function normalizeModel(layers, defaultValue, fontResources) {
|
||||
layer.font_id = fontIdForFile(fontResources, layer.font_file);
|
||||
delete layer.font_file;
|
||||
}
|
||||
const bounds = layers.map((layer) => ({
|
||||
bottom: layer.y + layer.height / 2,
|
||||
left: layer.x - layer.width / 2,
|
||||
right: layer.x + layer.width / 2,
|
||||
top: layer.y - layer.height / 2,
|
||||
}));
|
||||
const bounds = layers.map((layer) => {
|
||||
const anchorX = Number(layer.anchor_x ?? 0.5);
|
||||
const anchorY = Number(layer.anchor_y ?? 0.5);
|
||||
const radians = Number(layer.rotation ?? 0) * Math.PI / 180;
|
||||
const cosine = Math.cos(radians);
|
||||
const sine = Math.sin(radians);
|
||||
const corners = [
|
||||
[-anchorX * layer.width, -anchorY * layer.height],
|
||||
[(1 - anchorX) * layer.width, -anchorY * layer.height],
|
||||
[-anchorX * layer.width, (1 - anchorY) * layer.height],
|
||||
[(1 - anchorX) * layer.width, (1 - anchorY) * layer.height],
|
||||
].map(([x, y]) => ({
|
||||
x: layer.x + x * Number(layer.scale_x ?? 1) * cosine - y * Number(layer.scale_y ?? 1) * sine,
|
||||
y: layer.y + x * Number(layer.scale_x ?? 1) * sine + y * Number(layer.scale_y ?? 1) * cosine,
|
||||
}));
|
||||
return {
|
||||
bottom: Math.max(...corners.map((item) => item.y)),
|
||||
left: Math.min(...corners.map((item) => item.x)),
|
||||
right: Math.max(...corners.map((item) => item.x)),
|
||||
top: Math.min(...corners.map((item) => item.y)),
|
||||
};
|
||||
});
|
||||
const left = Math.min(...bounds.map((item) => item.left));
|
||||
const right = Math.max(...bounds.map((item) => item.right));
|
||||
const top = Math.min(...bounds.map((item) => item.top));
|
||||
@@ -651,7 +724,7 @@ export function compileTextTemplateAssets({ templateDirectory, templateId }) {
|
||||
sourcePath,
|
||||
}));
|
||||
const imageIds = new Map(imagePaths.map((path, index) => [path, imageResources[index].assetId]));
|
||||
const manifestMappings = manifestFileMap(packageFiles);
|
||||
const { mappings: manifestMappings, spriteDefinitions } = manifestFileMap(packageFiles);
|
||||
const unresolvedImages = [];
|
||||
const prefabCandidates = packageFiles.filter((path) => extname(path).toLowerCase() === ".prefab").flatMap((path) => {
|
||||
let prefab;
|
||||
@@ -660,7 +733,7 @@ export function compileTextTemplateAssets({ templateDirectory, templateId }) {
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
const layers = prefabLayers(prefab, { imageIds, manifestMappings, unresolvedImages });
|
||||
const layers = prefabLayers(prefab, { imageIds, manifestMappings, spriteDefinitions, unresolvedImages });
|
||||
const texts = layers.filter((layer) => layer.type === "text").map((layer) => layer.text.trim().toLocaleLowerCase("zh-CN"));
|
||||
const expected = [metadata.default_text, metadata.runtime?.layer?.default_text, ...(metadata.runtime?.human_strings ?? [])]
|
||||
.filter((value) => typeof value === "string" && value.trim()).map((value) => value.trim().toLocaleLowerCase("zh-CN"));
|
||||
|
||||
Reference in New Issue
Block a user