Improve armor equipment icon silhouettes

This commit is contained in:
2026-07-10 00:24:56 +09:00
parent 0e1613d1da
commit 2aedbdd71c
5 changed files with 280 additions and 99 deletions

View File

@@ -313,58 +313,84 @@ function buildRecommendations(itemRows, groupedRows) {
'sky-piercer-halberd',
'western-cavalry-spear'
];
const weaponPolearmRows = itemRows.filter((row) => weaponPolearmTargetIds.includes(row.itemId));
const armorIds = itemRows.filter((row) => row.slot === 'armor').map((row) => row.itemId);
const armorTargetIds = ['oath-robe', 'reinforced-lamellar', 'cloth-armor', 'lamellar-armor', 'rebel-vest'];
const accessoryIds = itemRows.filter((row) => row.slot === 'accessory').map((row) => row.itemId);
const weaponPolearmComplete =
weaponPolearmRows.length === weaponPolearmTargetIds.length &&
weaponPolearmRows.every((row) => row.icon && row.primitiveCount >= 18) &&
new Set(weaponPolearmRows.map((row) => row.signature)).size === weaponPolearmRows.length;
const completedTargets = weaponPolearmComplete
? [
{
title: 'weapon spear/polearm family',
itemIds: weaponPolearmRows.map((row) => row.itemId),
reason: 'The previous shared spear/polearm silhouettes now use item-specific helper shapes with enough primitive detail for 20px and 30px equipment UI reads.'
}
]
: [];
const targets = [
{
title: 'weapon spear/polearm family',
itemIds: weaponPolearmTargetIds,
completeReason:
'The previous shared spear/polearm silhouettes now use item-specific helper shapes with enough primitive detail for 20px and 30px equipment UI reads.',
openReason:
'These are high-frequency equipment surfaces and several treasure/common weapons share a thin diagonal shaft silhouette; upgrading this group gives the clearest identity gain in sortie prep and equipment swap screens.',
successCriteria:
'Each item should read as a distinct weapon silhouette at 20px and 30px, with treasure weapons visibly richer than common weapons.'
},
{
title: 'armor silhouettes',
itemIds: armorTargetIds,
completeReason:
'The previous shared armor and robe silhouettes now use item-specific helper shapes with stronger outer contours and material cues.',
openReason:
'Armor and robes are readable but still depend on simple triangular torsos and small color accents; this is now the largest remaining shared-equipment silhouette group.',
successCriteria:
'Each armor item should keep its slot identity while gaining a distinct outer silhouette and material cue at 20px and 30px.'
},
{
title: 'accessory charms and tokens',
itemIds: accessoryIds,
completeReason:
'Accessory icons now use distinct badge, scroll, charm, pouch, manual, and quiver silhouettes at small camp UI sizes.',
openReason: 'Accessories are the smallest UI read and several use compact badge-like shapes.',
successCriteria:
'Each accessory should keep a compact footprint while gaining a distinct readable prop shape at 20px and 30px.'
}
].map((target) => ({
...target,
rows: itemRows.filter((row) => target.itemIds.includes(row.itemId))
}));
const completedTargets = targets
.filter((target) => improvementTargetComplete(target))
.map((target) => ({
title: target.title,
itemIds: target.rows.map((row) => row.itemId),
reason: target.completeReason
}));
const nextTarget =
targets.find((target) => !improvementTargetComplete(target)) ?? {
title: 'remaining low-detail equipment icons',
rows: itemRows.filter((row) => row.concerns.length > 0),
openReason: 'All named batches are complete; remaining work should be selected from the low-detail inventory rows.',
successCriteria: 'Clear remaining low-detail concerns without changing stable texture keys.'
};
const nextTargetIndex = targets.findIndex((target) => target.title === nextTarget.title);
const followUps = targets
.filter((target, index) => index > nextTargetIndex && !improvementTargetComplete(target))
.map((target) => ({
title: target.title,
itemIds: target.rows.map((row) => row.itemId),
reason: target.openReason
}));
return {
completedTargets,
firstTargetTitle: weaponPolearmComplete ? 'armor silhouettes' : 'weapon spear/polearm family',
firstTargetIds: weaponPolearmComplete ? armorIds : weaponPolearmRows.map((row) => row.itemId),
firstTargetReason: weaponPolearmComplete
? 'Armor and robes are readable but still depend on simple triangular torsos and small color accents; this is now the largest remaining shared-equipment silhouette group.'
: 'These are high-frequency equipment surfaces and several treasure/common weapons share a thin diagonal shaft silhouette; upgrading this group gives the clearest identity gain in sortie prep and equipment swap screens.',
firstTargetSuccessCriteria: weaponPolearmComplete
? 'Each armor item should keep its slot identity while gaining a distinct outer silhouette and material cue at 20px and 30px.'
: 'Each item should read as a distinct weapon silhouette at 20px and 30px, with treasure weapons visibly richer than common weapons.',
followUps: weaponPolearmComplete
? [
{
title: 'accessory charms and tokens',
itemIds: accessoryIds,
reason: 'Accessories are the smallest UI read and several use compact badge-like shapes.'
}
]
: [
{
title: 'armor silhouettes',
itemIds: armorIds,
reason: 'Armor and robes are readable but depend on simple triangular torsos and small color accents.'
},
{
title: 'accessory charms and tokens',
itemIds: accessoryIds,
reason: 'Accessories are the smallest UI read and several use compact badge-like shapes.'
}
],
firstTargetTitle: nextTarget.title,
firstTargetIds: nextTarget.rows.map((row) => row.itemId),
firstTargetReason: nextTarget.openReason,
firstTargetSuccessCriteria: nextTarget.successCriteria,
followUps,
topRiskGroups: groupedRows.slice(0, 5)
};
}
function improvementTargetComplete(target) {
return (
target.rows.length === target.itemIds.length &&
target.rows.every((row) => row.icon && row.primitiveCount >= 18) &&
new Set(target.rows.map((row) => row.signature)).size === target.rows.length
);
}
function renderReport({ iconSourceSize, iconTextureSize, itemRows, groupedRows, recommendations, sceneUsage }) {
const slotCounts = countBy(itemRows, (row) => row.slot);
const rankCounts = countBy(itemRows, (row) => row.rank);
@@ -403,13 +429,7 @@ function renderReport({ iconSourceSize, iconTextureSize, itemRows, groupedRows,
`- Item ids: ${recommendations.firstTargetIds.map((itemId) => `\`${itemId}\``).join(', ')}`,
`- Reason: ${recommendations.firstTargetReason}`,
'',
'## Follow-Up Targets',
'',
...recommendations.followUps.flatMap((target) => [
`- ${target.title}: ${target.itemIds.map((itemId) => `\`${itemId}\``).join(', ')}`,
` - ${target.reason}`
]),
'',
...renderFollowUpTargets(recommendations.followUps),
'## Highest-Risk Shared Silhouette Groups',
'',
'| score | signature | slots | ranks | items |',
@@ -463,6 +483,22 @@ function renderCompletedTargets(completedTargets) {
];
}
function renderFollowUpTargets(followUps) {
if (!followUps.length) {
return [];
}
return [
'## Follow-Up Targets',
'',
...followUps.flatMap((target) => [
`- ${target.title}: ${target.itemIds.map((itemId) => `\`${itemId}\``).join(', ')}`,
` - ${target.reason}`
]),
''
];
}
function countBy(rows, keySelector) {
return rows.reduce((counts, row) => {
const key = keySelector(row);