Remove comments that only restate the code, keeping the section banners and the notes that carry a reason, a measured fact or an external contract. ButtonOptions.width claimed to be a fixed width but only set minWidth, so the Graph and Texture pickers grew with the name they showed. It is now what it promises, with a separate minWidth for the buttons that have two forms. Narrow buttons shrink their padding, otherwise a 24px icon button had 8px left for its glyph and truncate dropped it entirely. __gm.labelsDropped() guards that class: the overflow guard only saw text that was too wide, never a label truncated to nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
53 lines
1.9 KiB
TypeScript
53 lines
1.9 KiB
TypeScript
import type { TextureAsset, TextureFrame } from '../model/Asset';
|
||
import { findAsset, type Project } from '../model/Project';
|
||
import { findFrame } from '../model/texture';
|
||
|
||
export const NO_TEXTURE_LABEL = 'None';
|
||
|
||
const FRAME_SEPARATOR = ' / ';
|
||
|
||
export interface TextureChoice {
|
||
/** Asset id for the whole picture, frame id for one cut-out of it. */
|
||
id: string;
|
||
label: string;
|
||
asset: TextureAsset;
|
||
/** Null for the whole-picture entry. */
|
||
frame: TextureFrame | null;
|
||
}
|
||
|
||
/**
|
||
* The texture's name, "Sheet / Frame" for a frame, "None" for the empty id, `<id>?` when it no
|
||
* longer resolves – a dangling reference shows its id rather than passing for an empty field.
|
||
*/
|
||
export function textureRefLabel(project: Project | null, id: string): string {
|
||
if (id === '') return NO_TEXTURE_LABEL;
|
||
if (!project) return `${id}?`;
|
||
const asset = findAsset(project, id);
|
||
if (asset) return asset.type === 'texture' ? asset.name : `${id}?`;
|
||
const found = findFrame(project, id);
|
||
return found ? `${found.asset.name}${FRAME_SEPARATOR}${found.frame.name}` : `${id}?`;
|
||
}
|
||
|
||
/**
|
||
* Everything a sprite may wear, in menu order: each texture followed by its own frames. Textures
|
||
* are sorted by name so the order does not depend on upload time; frames keep creation order,
|
||
* which for a sliced sheet is reading order.
|
||
*/
|
||
export function textureRefChoices(project: Project): TextureChoice[] {
|
||
const textures = project.assets
|
||
.filter((a): a is TextureAsset => a.type === 'texture')
|
||
.sort((a, b) => a.name.localeCompare(b.name));
|
||
const choices: TextureChoice[] = [];
|
||
for (const asset of textures) {
|
||
choices.push({ id: asset.id, label: asset.name, asset, frame: null });
|
||
for (const frame of asset.frames)
|
||
choices.push({
|
||
id: frame.id,
|
||
label: `${asset.name}${FRAME_SEPARATOR}${frame.name}`,
|
||
asset,
|
||
frame,
|
||
});
|
||
}
|
||
return choices;
|
||
}
|