Trim needless comments and fix the picker width

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>
This commit is contained in:
rootandClaude Opus 5 committed 2026-09-08 15:52:05 +02:00
1 parent f16801aef3
commit 4d84231b9f
115 files changed
+707 -1564

No files matched your search

+10 -25
View File
@@ -4,21 +4,15 @@ import type { TextureRef } from '../core/model/texture';
const DEFAULT_BASE = '/game-maker/data/textures';
/**
* Keeps uploaded images on the GPU, keyed by their file name.
*
* Nothing is ever evicted, and that is safe rather than sloppy: file names are content
* addressed, so a name cannot come to mean different bytes and a cached texture cannot go
* stale. It also means the same picture used by a hundred sprites is uploaded once.
*
* A miss is not an error – it starts the load and reports "not yet", so the caller draws its
* plain colour in the meantime and gets a redraw when the picture arrives. That is why a
* sprite never flickers and why nothing here needs to be awaited.
* Keeps uploaded images on the GPU, keyed by file name. Nothing is evicted: file names are
* content addressed, so a cached texture can never go stale. A miss is not an error – it starts
* the load and reports "not yet", so callers never await and get a redraw when the picture lands.
*/
export class TextureLibrary {
private base = DEFAULT_BASE;
private readonly loaded = new Map<string, Texture>();
private readonly loading = new Set<string>();
/** Files whose load failed; retried never, so one broken reference cannot spam the network. */
/** Never retried, so one broken reference cannot spam the network. */
private readonly failed = new Set<string>();
private readonly listeners = new Set<() => void>();
@@ -28,12 +22,9 @@ export class TextureLibrary {
}
/**
* The picture if it is already in memory, otherwise null while it loads.
*
* Caveat of content addressing: two texture *assets* can name the same file (the same image
* uploaded twice) while disagreeing about `smooth`. The scale mode belongs to the shared
* source, so the last one drawn wins – deterministically, since draw order is stable. The
* upload avoids creating that situation by reusing an existing asset for a known file.
* The picture if it is in memory, otherwise null while it loads. The scale mode belongs to the
* shared source, so two assets naming the same file with different `smooth` fight over it and
* the last one drawn wins; upload avoids that by reusing the existing asset for a known file.
*/
get(ref: TextureRef): Texture | null {
const texture = this.loaded.get(ref.file);
@@ -44,16 +35,14 @@ export class TextureLibrary {
const mode = ref.smooth ? 'linear' : 'nearest';
if (texture.source.scaleMode !== mode) {
texture.source.scaleMode = mode;
// Assigning the mode alone is not enough, and the difference is invisible until a reload:
// Pixi's `scaleMode` setter only writes mag/min/mipmapFilter and leaves the style's cached
// `_sharedResourceId` in place – but that id is the key the GPU sampler is looked up under,
// so the old sampler keeps being used. `update()` drops the id and announces the change.
// Pixi's `scaleMode` setter leaves the style's cached `_sharedResourceId` stale, so the old
// GPU sampler keeps being used until a reload; `update()` drops the id.
texture.source.style.update();
}
return texture;
}
/** Runs `fn` whenever a picture has arrived. Returns the unsubscribe. */
/** Runs `fn` whenever a picture has arrived; returns the unsubscribe. */
onChange(fn: () => void): () => void {
this.listeners.add(fn);
return () => this.listeners.delete(fn);
@@ -77,8 +66,4 @@ export class TextureLibrary {
}
}
/**
* The one library. A second instance would only duplicate GPU uploads – the cache is keyed by
* content, so there is nothing an instance could hold that another should not share.
*/
export const textureLibrary = new TextureLibrary();