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:
1 parent
f16801aef3
commit
4d84231b9f
115 files changed
+707
-1564
No files matched your search
+33
-32
@@ -1,11 +1,11 @@
|
||||
import { type Application, type Container, Rectangle, Text } from 'pixi.js';
|
||||
import { ui, Widget } from '../ui';
|
||||
import { Button, ui, Widget } from '../ui';
|
||||
import type { CentreTab, Editor } from './Editor';
|
||||
import type { EditorState } from './state';
|
||||
|
||||
/**
|
||||
* Installs `window.__gm`, which the check scripts in tools/ use to find widgets by their
|
||||
* visible text and to read editor state. Read-only access; harmless in production.
|
||||
* visible text and to read editor state.
|
||||
*/
|
||||
export function installDebugHook(app: Application, state: EditorState, editor: Editor): void {
|
||||
const { viewport, gameView, graphEditor, textureEditor, hierarchy } = editor;
|
||||
@@ -25,8 +25,7 @@ export function installDebugHook(app: Application, state: EditorState, editor: E
|
||||
for (const child of node.children) walk(child);
|
||||
};
|
||||
walk(app.stage);
|
||||
// TypeScript does not track the assignment inside `walk`, so it believes `found` is still
|
||||
// `null` here – hence both the disable and the cast below.
|
||||
// TypeScript does not track the assignment inside `walk`, hence the disable and the cast.
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!found) return null;
|
||||
const node = found as Text;
|
||||
@@ -51,13 +50,9 @@ export function installDebugHook(app: Application, state: EditorState, editor: E
|
||||
return out;
|
||||
};
|
||||
/**
|
||||
* Visible texts drawn wider than the widget that owns them – the shape of bug where a label
|
||||
* runs past its own control instead of being shortened to fit.
|
||||
*
|
||||
* The owner's box is its declared `w`/`h` at its global position, NOT `getBounds()`: a Pixi
|
||||
* container has no size of its own, so its bounds are the union of its children – including
|
||||
* the very text that overflows, which makes every overflow measure as zero. Texts inside a
|
||||
* scroll container are skipped, where sticking out is the point and the mask hides it.
|
||||
* Visible texts drawn wider than the widget that owns them. The owner's box is its declared
|
||||
* `w`/`h`, not `getBounds()`: a Pixi container's bounds are the union of its children –
|
||||
* including the overflowing text – so every overflow would measure as zero.
|
||||
*/
|
||||
const textOverflows = (all = false): { text: string; owner: string; over: number }[] => {
|
||||
const out: { text: string; owner: string; over: number }[] = [];
|
||||
@@ -65,11 +60,9 @@ export function installDebugHook(app: Application, state: EditorState, editor: E
|
||||
if (!node.visible) return;
|
||||
const isWidget = node instanceof Widget;
|
||||
const box = isWidget ? node : owner;
|
||||
// A mask further up – a panel clipping its contents – does not excuse a label spilling
|
||||
// out of its own control, so the question restarts at every widget. Only a mask at or
|
||||
// below the owner (a text field's scroll window, a scroll container) makes it intended.
|
||||
// `Boolean`, not `!== null`: Pixi's mask getter returns `undefined` when nothing masks,
|
||||
// so comparing against null marks every container as clipped and hides every finding.
|
||||
// A mask further up does not excuse a label spilling out of its own control, so the
|
||||
// question restarts at every widget. `Boolean`, not `!== null`: Pixi's mask getter
|
||||
// returns `undefined` when nothing masks.
|
||||
const masked = (isWidget ? false : clipped) || Boolean(node.mask);
|
||||
if (node instanceof Text) {
|
||||
if (!box || !node.text || (masked && !all)) return;
|
||||
@@ -86,6 +79,22 @@ export function installDebugHook(app: Application, state: EditorState, editor: E
|
||||
walk(app.stage, null, false);
|
||||
return out;
|
||||
};
|
||||
/**
|
||||
* The counterpart of `textOverflows`: buttons whose label was shortened away to nothing, which
|
||||
* leaves a control that says nothing at all. An empty `Text` is invisible to the overflow walk.
|
||||
*/
|
||||
const labelsDropped = (): { text: string; owner: string; w: number }[] => {
|
||||
const out: { text: string; owner: string; w: number }[] = [];
|
||||
const walk = (node: Container): void => {
|
||||
if (!node.visible) return;
|
||||
if (node instanceof Button && node.text && !node.shownText) {
|
||||
out.push({ text: node.text, owner: node.constructor.name, w: node.w });
|
||||
}
|
||||
for (const child of node.children) walk(child);
|
||||
};
|
||||
walk(app.stage);
|
||||
return out;
|
||||
};
|
||||
/** Screen rectangle of the open popup (the backdrop is not a widget), or null when none is. */
|
||||
const overlayRect = (): { x: number; y: number; w: number; h: number } | null => {
|
||||
const popups = ui().overlay.children.filter((node): node is Widget => node instanceof Widget);
|
||||
@@ -100,33 +109,30 @@ export function installDebugHook(app: Application, state: EditorState, editor: E
|
||||
overlayTexts,
|
||||
overlayRect,
|
||||
textOverflows,
|
||||
labelsDropped,
|
||||
viewportCenter: () => centreOf(viewport),
|
||||
viewportInfo: () => viewport.debugInfo(),
|
||||
gameInfo: () => gameView.debugInfo(),
|
||||
layerOf: (id: string) => viewport.layerOf(id),
|
||||
drawOrder: () => viewport.drawOrder(),
|
||||
/** Screen position of an object in the Scene tab (its drawn position through the view). */
|
||||
objectScreen: (id: string) => viewport.objectScreen(id),
|
||||
/** The rectangle it covers on screen – for sampling colours inside it with `pixelAt`. */
|
||||
objectRect: (id: string) => viewport.objectRect(id),
|
||||
/** The same for the Game tab (through the camera), so tests can click what the player sees. */
|
||||
/** The same for the Game tab – through the camera, so what the player sees. */
|
||||
gameScreen: (id: string) => gameView.objectScreen(id),
|
||||
graph: {
|
||||
current: () => graphEditor.currentAssetId,
|
||||
portAt: (nodeId: string, port: string, isOutput: boolean) =>
|
||||
graphEditor.canvas.portGlobal(nodeId, port, isOutput),
|
||||
nodeAt: (nodeId: string) => graphEditor.canvas.nodeGlobal(nodeId),
|
||||
// The canvas, not the whole tab: a point measured through the header would sit above
|
||||
// the drawing area a right-click test aims at.
|
||||
// The canvas, not the whole tab: a centre measured through the header sits above the
|
||||
// drawing area.
|
||||
center: () => centreOf(graphEditor.canvas),
|
||||
pickerWidth: () => graphEditor.pickerWidth,
|
||||
},
|
||||
texture: {
|
||||
current: () => textureEditor.currentAssetId,
|
||||
/**
|
||||
* Where an image pixel of the shown sheet sits on screen. Frames are dragged in image
|
||||
* coordinates, so without this a check could only drag somewhere and hope – it could not
|
||||
* aim at a known part of the picture and then assert which part came out.
|
||||
*/
|
||||
pickerWidth: () => textureEditor.pickerWidth,
|
||||
/** Where an image pixel of the shown sheet sits on screen (frames are dragged in image coordinates). */
|
||||
pointAt: (x: number, y: number) => textureEditor.imageToScreen(x, y),
|
||||
},
|
||||
world: () => editor.worldSnapshot(),
|
||||
@@ -135,12 +141,7 @@ export function installDebugHook(app: Application, state: EditorState, editor: E
|
||||
hierarchyChevron: (id: string) => hierarchy.chevronPosition(id),
|
||||
hierarchyExpandAll: () => hierarchy.expandAll(),
|
||||
hierarchyCollapseAll: () => hierarchy.collapseAll(),
|
||||
/**
|
||||
* The colour actually on screen at a point, as `#rrggbb`. Everything else here reports what
|
||||
* the model *says*; this is the only way a check can assert what was really drawn – which is
|
||||
* the whole question for a texture, since a textured and an untextured sprite are identical
|
||||
* in the model apart from one property.
|
||||
*/
|
||||
/** The colour actually on screen at a point, as `#rrggbb` – what was drawn, not what the model says. */
|
||||
pixelAt: (x: number, y: number) => {
|
||||
const { pixels } = app.renderer.extract.pixels({
|
||||
target: app.stage,
|
||||
|
||||
Reference in new issue
Block a user